($INBOX_DIR/description missing)  
help / color / mirror / Atom feed
[PATCH 2/8] Pass all scan keys to BRIN consistent function at once
280+ messages / 2 participants
[nested] [flat]

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c          | 158 +++++++++++++++++++-----
 src/backend/access/brin/brin_validate.c |   4 +-
 2 files changed, 126 insertions(+), 36 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..963b7079cf 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,78 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of
+					 * multiple scan keys. We can determine that based on the
+					 * number of arguments - functions with extra parameter
+					 * (number of scan keys) do support this, otherwise we
+					 * have to simply pass the scan keys one by one, as
+					 * before.
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same
+						 * for all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet
+						 * the criteria for a single one of them is enough to
+						 * discard the range as a whole, so break out of the
+						 * loop as soon as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+
+							/* mismatching key, no need to look further  */
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-- 
2.26.2


--------------AC3FFB734F56C5F52D422EFC
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Process-all-scan-keys-in-existing-BRIN-opcl-20210305.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Process-all-scan-keys-in-existing-BRIN-opcl-20210305.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/6] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 158 ++++++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 140 ++++++++++++++------
 src/backend/access/brin/brin_minmax.c    |  92 ++++++++++---
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 303 insertions(+), 95 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..963b7079cf 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,78 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of
+					 * multiple scan keys. We can determine that based on the
+					 * number of arguments - functions with extra parameter
+					 * (number of scan keys) do support this, otherwise we
+					 * have to simply pass the scan keys one by one, as
+					 * before.
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same
+						 * for all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet
+						 * the criteria for a single one of them is enough to
+						 * discard the range as a whole, so break out of the
+						 * loop as soon as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+
+							/* mismatching key, no need to look further  */
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..a260074c91 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -251,6 +253,10 @@ brin_inclusion_add_value(PG_FUNCTION_ARGS)
 /*
  * BRIN inclusion consistent function
  *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
+ *
  * All of the strategies are optional.
  */
 Datum
@@ -258,24 +264,31 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/* Handle IS NULL/IS NOT NULL tests */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -284,7 +297,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -293,7 +311,14 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
@@ -301,10 +326,45 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all regular scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* Skip IS NULL/IS NOT NULL keys (already handled above). */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
+	/* This should be called only for regular keys, not for IS [NOT] NULL. */
+	Assert(!(key->sk_flags & SK_ISNULL));
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +384,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +444,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +464,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +483,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +518,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +528,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..e116084a02 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -140,29 +142,41 @@ brin_minmax_add_value(PG_FUNCTION_ARGS)
  * Given an index tuple corresponding to a certain page range and a scan key,
  * return whether the scan key is consistent with the index tuple's min/max
  * values.  Return true if so, false otherwise.
+ *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
  */
 Datum
 brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
 	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -171,7 +185,12 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -180,13 +199,52 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
+	}
+
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
+
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +287,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 1487710d59..33841e14f2 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8191,7 +8191,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------6A37408A2C42B5B56C3B3D49
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210303.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210303.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c          | 158 +++++++++++++++++++-----
 src/backend/access/brin/brin_validate.c |   4 +-
 2 files changed, 126 insertions(+), 36 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..963b7079cf 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,78 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of
+					 * multiple scan keys. We can determine that based on the
+					 * number of arguments - functions with extra parameter
+					 * (number of scan keys) do support this, otherwise we
+					 * have to simply pass the scan keys one by one, as
+					 * before.
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same
+						 * for all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet
+						 * the criteria for a single one of them is enough to
+						 * discard the range as a whole, so break out of the
+						 * loop as soon as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+
+							/* mismatching key, no need to look further  */
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-- 
2.26.2


--------------AC3FFB734F56C5F52D422EFC
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Process-all-scan-keys-in-existing-BRIN-opcl-20210305.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Process-all-scan-keys-in-existing-BRIN-opcl-20210305.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c          | 158 +++++++++++++++++++-----
 src/backend/access/brin/brin_validate.c |   4 +-
 2 files changed, 126 insertions(+), 36 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..f9a0476024 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,78 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any scan keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of
+					 * multiple scan keys. We can determine that based on the
+					 * number of arguments - functions with extra parameter
+					 * (number of scan keys) do support this, otherwise we
+					 * have to simply pass the scan keys one by one, as
+					 * before.
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same
+						 * for all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet
+						 * the criteria for a single one of them is enough to
+						 * discard the range as a whole, so break out of the
+						 * loop as soon as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+
+							/* mismatching key, no need to look further  */
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-- 
2.26.2


--------------82D677E9F94AC7574E460205
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Process-all-scan-keys-in-existing-BRIN-opcl-20210308.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Process-all-scan-keys-in-existing-BRIN-opcl-20210308.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c          | 158 +++++++++++++++++++-----
 src/backend/access/brin/brin_validate.c |   4 +-
 2 files changed, 126 insertions(+), 36 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..f9a0476024 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,78 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any scan keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of
+					 * multiple scan keys. We can determine that based on the
+					 * number of arguments - functions with extra parameter
+					 * (number of scan keys) do support this, otherwise we
+					 * have to simply pass the scan keys one by one, as
+					 * before.
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same
+						 * for all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet
+						 * the criteria for a single one of them is enough to
+						 * discard the range as a whole, so break out of the
+						 * loop as soon as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+
+							/* mismatching key, no need to look further  */
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-- 
2.26.2


--------------556A1DC61262AF15641DB204
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Process-all-scan-keys-in-existing-BRIN-opc-20210308b.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Process-all-scan-keys-in-existing-BRIN-opc-20210308b.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow future opclases to benefit from seeing all keys at once.

This does break existing BRIN opclasses, because the signature of the
consistent function changed. We might support both variants (with 3 and
4 parameters), but that seems pointless - the changes to NULL handling
likely require updates too. So better to make the failure clear. Also,
we're not aware of any out-of-core opclasses - there may be some, but
probably not many.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 doc/src/sgml/brin.sgml                   |   8 +-
 src/backend/access/brin/brin.c           | 118 +++++++++++++------
 src/backend/access/brin/brin_inclusion.c | 140 ++++++++++++++++-------
 src/backend/access/brin/brin_minmax.c    |  92 ++++++++++++---
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 6 files changed, 269 insertions(+), 97 deletions(-)

diff --git a/doc/src/sgml/brin.sgml b/doc/src/sgml/brin.sgml
index 06880c0f7b..078f51bb55 100644
--- a/doc/src/sgml/brin.sgml
+++ b/doc/src/sgml/brin.sgml
@@ -464,12 +464,14 @@ typedef struct BrinOpcInfo
 
    <varlistentry>
     <term><function>bool consistent(BrinDesc *bdesc, BrinValues *column,
-       ScanKey key)</function></term>
+       ScanKey *keys, int nkeys)</function></term>
     <listitem>
      <para>
-      Returns whether the ScanKey is consistent with the given indexed
-      values for a range.
+      Returns whether all the ScanKey entries are consistent with the given
+      indexed values for a range.
       The attribute number to use is passed as part of the scan key.
+      Multiple scan keys for the same attribute may be passed at once, the
+      number of entries is determined by the <literal>nkeys</literal> parameter.
      </para>
     </listitem>
    </varlistentry>
diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..743f2a925a 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,40 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
+					Oid			collation;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
-
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
-
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					/* skip attributes without any scan keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
+
+					bval = &dtup->bt_columns[attno - 1];
+
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * XXX We simply use the collation from the first key (it
+					 * has to be the same for all keys for the same attribue).
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
+					collation = keys[attno - 1][0]->sk_collation;
+
+					/* Check all keys at once */
+					add = FunctionCall4Coll(&consistentFn[attno - 1],
+											collation,
 											PointerGetDatum(bdesc),
 											PointerGetDatum(bval),
-											PointerGetDatum(key));
+											PointerGetDatum(keys[attno - 1]),
+											Int32GetDatum(nkeys[attno - 1]));
 					addrange = DatumGetBool(add);
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..a260074c91 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -251,6 +253,10 @@ brin_inclusion_add_value(PG_FUNCTION_ARGS)
 /*
  * BRIN inclusion consistent function
  *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
+ *
  * All of the strategies are optional.
  */
 Datum
@@ -258,24 +264,31 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/* Handle IS NULL/IS NOT NULL tests */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -284,7 +297,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -293,7 +311,14 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
@@ -301,10 +326,45 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all regular scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* Skip IS NULL/IS NOT NULL keys (already handled above). */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
+	/* This should be called only for regular keys, not for IS [NOT] NULL. */
+	Assert(!(key->sk_flags & SK_ISNULL));
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +384,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +444,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +464,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +483,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +518,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +528,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..e116084a02 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -140,29 +142,41 @@ brin_minmax_add_value(PG_FUNCTION_ARGS)
  * Given an index tuple corresponding to a certain page range and a scan key,
  * return whether the scan key is consistent with the index tuple's min/max
  * values.  Return true if so, false otherwise.
+ *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
  */
 Datum
 brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
 	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -171,7 +185,12 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -180,13 +199,52 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
+	}
+
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
+
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +287,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..2c4f9a3eff 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											4, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index c7619f8cd3..cd1eda38ab 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8223,7 +8223,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------D524CD37E77B36A2883A7617
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Move-IS-NOT-NULL-handling-from-BRIN-support-20210311.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Move-IS-NOT-NULL-handling-from-BRIN-support-20210311.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 1f72562c60..ccf609e799 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -389,6 +389,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -410,6 +413,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -470,7 +528,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -480,51 +538,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 986f76bd9b..b1b3ce700d 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 4b5d6a7213..b233558310 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index fb0615463e..0c28137c8f 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index e6c7b070f6..9c11c3af3a 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8135,7 +8135,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8151,7 +8151,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------45196B023835614BDFCBD16D
Content-Type: application/vnd.oasis.opendocument.spreadsheet;
 name="results.ods"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
 filename="results.ods"

UEsDBBQAAAgAAAW+k1GFbDmKLgAAAC4AAAAIAAAAbWltZXR5cGVhcHBsaWNhdGlvbi92bmQu
b2FzaXMub3BlbmRvY3VtZW50LnNwcmVhZHNoZWV0UEsDBBQAAAgAAAW+k1FMwsZq0hEAANIR
AAAYAAAAVGh1bWJuYWlscy90aHVtYm5haWwucG5niVBORw0KGgoAAAANSUhEUgAAAO0AAAD/
CAMAAAAqjaEtAAAAWlBMVEUjIyMqKiozMzM8PDxERERLS0tTU1NbW1tjY2Nra2tzc3N7e3uD
g4OMjIyTk5Oampqjo6Orq6uzs7O7u7vDw8PLy8vT09PZ2dnl5eXr6+vy8vL+/v4AAAD///83
nqiOAAARM0lEQVR42u1dh4KqOhTcVVJJIaQn//+fL0F37xYLICjuk3tXUUmZ5GSYHFLe8v/p
eHuhfaF9oX2hfaF9oX2hfaF9oZ2P1rv/zb+K9v9zvNCeO4yrr9Y9N1r3Zr3by66BkHgAIfMO
Ot/vrDfv1kt5vFRC453w/MnRqvfOs3dNKyy79w51rrxCopwEzJPee8eINDvsPNspJjhRVLie
tPYZ0TLaWggcgBhbhb0XVEMvWNd6qsrXBRMRrrGNc57zHgMpoN0bYDl7RrTQINIDt7fWesa9
p0K09h1D6KFtBShXFaCNAcWEcc9545i0gDcYyWdEW+qPaGyaihZ1VjQOK9xZu3egWDauaE0P
+3oCDO5KIZielAJ5vhZc0Drmme07jTDGjmLMSvM0bUFS8HjPunJW22jflcu5YL3wzKnOtaVd
P+sd6HvG3Y/34dR9vr7UxQvtC+0L7QvtC+0L7QvtC+0L7QvtC+0L7QvtC+3Zoy99Zz3Gs+e6
oa/dX7iiP/n74GFlD+6iCz3ksCnZUGPc1dW9UiDTC2illk6eQuvwnvaeatLCzkx0rVGKpKOY
OIbb1mAsHCkf6i/V8eM6jLTGtH7RlzeCWocItD0ixBEKJRIOI2beW4WgsTsCHTa4vHaY4iH+
crUpeRI1fnaIDfP+jXUI6Va2GFtL8KGyWlouq1nh5TIlGihb5jpua6bq75Jw1Ze6JUowDd3O
aAi0baagbbRpnHCNgp4wqO1eA3t4pCCIh6pxCvEDek686dxeVxdfY/Xe7SzhBtbvSqU2TqsS
B+xBBz0we9dVV6e3O8dbrWyjUKnQphRTQWAs8NKKFvWNMY50rhmsH/R2z1tPukZbSztgqShR
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
TVfN9Pjlf/x4Xg/yasZn5YHyn17l+tfyw+vKbxy/Of3x3Y2Lsw/n9U37j+M3H05uXP7z/UdF
lavXyfHHJ/Cyw+rP//n8+P20Cevh+O7sRv335btenZ6fvGxfeXN5/vFnnbXXyo3jdz/Wh6i/
/oW6mvrT3n1cwMVP5+VNd+Py7Mbr019/f/vaP6q05VazfN/fzy4LDy5q/vjV//3h4vL09T9n
E/pI9+XDPf6xLPqnTz+46XbQPprPv62K/Pb4/MeyO96cvC4r8dVKN+3mai6//pbpR32umUUd
fvrPZ+o4+3BZnrAnV+ScvlT//MblT0WjP/50Y3YifPpBXQdVPX6Omc6Pz+4gZTnTH16c/n/l
DwFm6ml/1n7Jabldnb6c/nj6HRc/Hb+qL5lrv7xstZPzaQWfLW/5cT/PJPWuXMiO33y2pPrb
b5Tr/PG7ZQ2ffnHa/fNXl8V88vX2cxfAhp9eBZ7euW9Ofvn18nXlt3/8+srv//j19RV8hMxr
UPPwy5OVA+TABQcu2CsuWKxrL7hgwzcbc8H6CrbgAjLngtdU/zpwwYELDlywX1wQ9o8LXp/+
8q2SwLLT55948u7V9wdiOBDDLoghfkVi+IrXgMo5Z+evarj0093w+6WEg/kfzH8H5s/m9wKe
/nN4I+wJF7ye/nPgggMXnKT944LDG2Fnb4QDMRyIYSYGsXceXN98B2LYE2I4vB4OxDATQ94/
Yji8Hg5ccOCCHXABeHMyOLgSDmRwIIO9JIOvnZM4+f5vNAO5GgI4/vHsXTGTv7+5cXktPDB/
7bJ8+XyDyr9amGIxMpfC+8vvLs7enL767orBXCWZX7/3vG203/rmgVz06++9PHv/+TccCOpA
UH8QgvraiZKbCEqTQPnHpa9PV3ugqz8OXR3Suj+jq6+S1g1fO5dTT1efP7oOdHWgq0PA6HC7
ukJXXzvddA/oaosI1IGn9i2mdeCuA3ct3PU1M2L7uOvzXXngrgN3/Y6fiQfuMuCur53Ouwfc
dXgm/r6fiQe6OtDVQldfO+N4ZJTwKmtc/dOuIN2nNLDJ1FcNqf1pbdvz8+m7siFvTKqYbevT
xjjGhvWxmdi3YFr7YDpfOyf3Dxm/+q1SwUO4/Rs96Q/xq39+/fjV184U3gOH8IGuDnR1eJj8
IR4m+LVzmfeArgb6gA88tWsf8CF+deCuhbt2kXr9+41fHbhr19x1uHcduGvhrl1kZR8edIcH
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
AA8ADwDOAwAATzcBAAAA
--------------45196B023835614BDFCBD16D
Content-Type: application/x-shellscript;
 name="brin-bloom-test.sh"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
 filename="brin-bloom-test.sh"

IyEvYmluL2Jhc2gKCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCiMgUEFSQU1F
VEVSUyBGT1IgREFUQSBHRU5FUkFUT1IKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMj
IyMKClJVTlM9MTAKCiMgdGFibGUgc2hvdWxkIGJlIDFHQgpOVU1fUEFHRVM9MTMxMDcyCgoj
IHRhYmxlIHdpdGggYSBzaW5nbGUgaW50IGNvbHVtbgpST1dTX1BFUl9SQU5HRT0yMjYKCiMg
d2hhdCBudW1iZXIgb2YgcGFnZXMgc2hvdWxkIGNvbnRhaW4gdGhlCk1BVENISU5HX1BBR0VT
PSIxIDEwMDAgMTAwMDAiCgojIHJlc3VsdCBuYW1lClJFU1VMVD0kMQoKIyMjIyMjIyMjIyMj
IyMjIyMjIyMjIyMjIyMjIyMKIyBQQVJBTUVURVJTIEZPUiBJTkRFWCBCVUlMRAojIyMjIyMj
IyMjIyMjIyMjIyMjIyMjIyMjIyMjIwoKIyBCUklOIHJhbmdlIHNpemUKUEFHRVNfUEVSX1JB
TkdFPSIxIDQgOCAxNiAzMiA2NCAxMjggMjU2IgoKIyBibG9vbSBmYWxzZSBwb3NpdGl2ZQpG
QUxTRV9QT1NJVElWRVM9IjAuMDEgMC4wMjUgMC4wNSAwLjA3NSAwLjEgMC4xNSIKCkZJTExf
RkFDVE9SUz0iMTAwIDUwIDE1MCIKCkRBVEU9JChkYXRlICslWSVtJWQtJUglTSVTKQoKZWNo
byAicnVuCXR5cGUJbWF0Y2gJdGFibGVfcGFnZXMJcm93c19wZXJfcmFuZ2UJbWF0Y2hpbmdf
cGFnZXMJdG90YWxfcm93cwltb2R1bG9faW50ZXJ2YWwJcGFnZXNfcGVyX3JhbmdlCWZpbGxf
ZmFjdG9yCW5kaXN0aW5jdAluZGlzdGluY3RfdGFyZ2V0CWZhbHNlX3Bvc2l0aXZlX3JhdGUJ
aW5kZXhfcGFnZXMJcnVuCXNlZWQJdmFsdWUJdGltZQlyZW1vdmVkCXJvd3MiID4gcmVzdWx0
cy0kUkVTVUxULSREQVRFLmNzdgoKcHNxbCB0ZXN0IC1jICJkcm9wIHRhYmxlIGlmIGV4aXN0
cyB0Igpwc3FsIHRlc3QgLWMgImNyZWF0ZSB0YWJsZSB0IChhIGludCkiCgpSVU49MApTRUVE
PTAKCmZvciBtcCBpbiAkTUFUQ0hJTkdfUEFHRVM7IGRvCgoJcHNxbCB0ZXN0IC1jICJ0cnVu
Y2F0ZSB0IgoJcHNxbCB0ZXN0IC1jICJkcm9wIGluZGV4IGlmIGV4aXN0cyBpZHgiCgoJIyB0
b3RhbCBudW1iZXIgb2Ygcm93cyBpbiB0aGUgdGFibGUKCVRPVEFMX1JPV1M9JCgoTlVNX1BB
R0VTICogUk9XU19QRVJfUkFOR0UpKQoKCSMgaG93IG9mdGVuIHdlIG5lZWQgdG8gcmVwZWF0
IHRoZSB2YWx1ZXMsIHRvIGdldCB0aGUgZGVzaXJlZCBudW1iZXIKCSMgb2YgbWF0Y2hpbmcg
cGFnZXMKCU1PRFVMT19JTlRFUlZBTD0kKChUT1RBTF9ST1dTIC8gbXApKQoKCSMgZ2VuZXJh
dGUgZGF0YQoJcHNxbCB0ZXN0IC1jICJpbnNlcnQgaW50byB0IHNlbGVjdCBtb2QoaSwgJE1P
RFVMT19JTlRFUlZBTCkgZnJvbSBnZW5lcmF0ZV9zZXJpZXMoMSwgJFRPVEFMX1JPV1MpIHMo
aSkiCgoJZm9yIHBwciBpbiAkUEFHRVNfUEVSX1JBTkdFOyBkbwoKCQlORElTVElOQ1Q9JCgo
cHByICogUk9XU19QRVJfUkFOR0UpKQoKCQlmb3IgZmYgaW4gJEZJTExfRkFDVE9SUzsgZG8K
CgkJCSMgdXNlZCB0byBzaXplIHRoZSBibG9vbSBmaWx0ZXIgKHRvbyBzbWFsbCAvIHRvbyBs
YXJnZSkKCQkJTkRJU1RJTkNUX1RBUkdFVD0kKChORElTVElOQ1QgKiAxMDAgLyBmZikpCgoJ
CQlmb3IgZnByIGluICRGQUxTRV9QT1NJVElWRVM7IGRvCgoJCQkJaWYgWyAtZiAic3RvcCIg
XTsgdGhlbgoJCQkJCXJtICJzdG9wIgoJCQkJCWV4aXQKCQkJCWZpCgoJCQkJU0VFRD0kKChT
RUVEKzEwMDApKQoKCQkJCXBzcWwgdGVzdCAtYyAiZHJvcCBpbmRleCBpZiBleGlzdHMgaWR4
IgoJCQkJcHNxbCB0ZXN0IC1jICJjcmVhdGUgaW5kZXggaWR4IG9uIHQgdXNpbmcgYnJpbiAo
YSBpbnQ0X2Jsb29tX29wcyhuX2Rpc3RpbmN0X3Blcl9yYW5nZSA9ICRORElTVElOQ1RfVEFS
R0VULCBmYWxzZV9wb3NpdGl2ZV9yYXRlID0gJGZwciwgc29ydF9tb2RlID0gZmFsc2UpKSB3
aXRoIChwYWdlc19wZXJfcmFuZ2UgPSAkcHByKSIKCQkJCXBzcWwgdGVzdCAtYyAidmFjdXVt
IGFuYWx5emUgdCIKCgkJCQlpZHhfcGFnZXM9YHBzcWwgdGVzdCAtdCAtQSAtYyAic2VsZWN0
IHJlbHBhZ2VzIGZyb20gcGdfY2xhc3Mgd2hlcmUgcmVsbmFtZSA9ICdpZHgnImAKCgkJCQkj
IGluZGV4IG5vdCBidWlsdCAoZmlsdGVyIHRvbyBsYXJnZSkKCQkJCWlmIFsgIiRpZHhfcGFn
ZXMiID09ICIiIF07IHRoZW4KCQkJCQljb250aW51ZQoJCQkJZmkKCgkJCQkjIG1hdGNoZXMK
CQkJCWZvciBpIGluIGBzZXEgMSAkUlVOU2A7IGRvCgoJCQkJCVJVTj0kKChSVU4rMSkpCgoJ
CQkJCXY9YC4vcm5kLnB5ICQoKFNFRUQraSkpIDAgJCgoTU9EVUxPX0lOVEVSVkFMLTEpKWAK
CgkJCQkJcHNxbCB0ZXN0ID4gcGxhbi5sb2cgPDxFT0YKc2V0IGVuYWJsZV9zZXFzY2FuID0g
b2ZmOwpzZXQgbWF4X3BhcmFsbGVsX3dvcmtlcnNfcGVyX2dhdGhlciA9IDA7CmV4cGxhaW4g
YW5hbHl6ZSBzZWxlY3QgKiBmcm9tIHQgd2hlcmUgYSA9ICR2OwpcdGltaW5nCnNlbGVjdCBj
b3VudCgqKSBmcm9tIHQgd2hlcmUgYSA9ICR2OwpFT0YKCgkJCQkJZWNobyAiPT09PT0gUlVO
ICRSVU4gPT09PT0iID4+IHBsYW5zLSREQVRFLmxvZwoJCQkJCWNhdCBwbGFuLmxvZyA+PiBw
bGFucy0kREFURS5sb2cKCgkJCQkJdGltZT1gY2F0IHBsYW4ubG9nIHwgZ3JlcCAnXlRpbWUn
IHwgYXdrICd7cHJpbnQgJDJ9J2AKCQkJCQlyZW1vdmVkPWBjYXQgcGxhbi5sb2cgfCBncmVw
ICdSb3dzIFJlbW92ZWQgYnkgSW5kZXggUmVjaGVjaycgfCBhd2sgJ3twcmludCAkNn0nYAoK
CQkJCQlpZiBbICIkcmVtb3ZlZCIgPT0gIiIgXTsgdGhlbgoJCQkJCQlyZW1vdmVkPSIwIgoJ
CQkJCWZpCgoJCQkJCXJvd3M9YHBzcWwgdGVzdCAtdCAtQSAtYyAic2VsZWN0IGNvdW50KCop
IGZyb20gdCB3aGVyZSBhID0gICR2ImAKCgkJCQkJZWNobyAiJFJVTglpbnQ0CW1hdGNoCSRO
VU1fUEFHRVMJJFJPV1NfUEVSX1JBTkdFCSRtcAkkVE9UQUxfUk9XUwkkTU9EVUxPX0lOVEVS
VkFMCSRwcHIJJGZmCSRORElTVElOQ1QJJE5ESVNUSU5DVF9UQVJHRVQJJGZwcgkkaWR4X3Bh
Z2VzCSRpCSRTRUVECSR2CSR0aW1lCSRyZW1vdmVkCSRyb3dzIiA+PiByZXN1bHRzLSRSRVNV
TFQtJERBVEUuY3N2CgoJCQkJZG9uZQoKCQkJCSMgbm8gbWF0Y2hlcyAob3V0c2lkZSBtb2R1
bG8gaW50ZXJ2YWwpCgkJCQlmb3IgaSBpbiBgc2VxIDEgJFJVTlNgOyBkbwoKCQkJCQlSVU49
JCgoUlVOKzEpKQoKCQkJCQl2PWAuL3JuZC5weSAkKChTRUVEK2kpKSAkTU9EVUxPX0lOVEVS
VkFMICQoKE1PRFVMT19JTlRFUlZBTCoyKSlgCgoJCQkJCXBzcWwgdGVzdCA+IHBsYW4ubG9n
IDw8RU9GCnNldCBlbmFibGVfc2Vxc2NhbiA9IG9mZjsKc2V0IG1heF9wYXJhbGxlbF93b3Jr
ZXJzX3Blcl9nYXRoZXIgPSAwOwpleHBsYWluIGFuYWx5emUgc2VsZWN0ICogZnJvbSB0IHdo
ZXJlIGEgPSAkdjsKXHRpbWluZwpzZWxlY3QgY291bnQoKikgZnJvbSB0IHdoZXJlIGEgPSAk
djsKRU9GCgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWNobyAi
PT09PT0gUlVOICRSVU4gPT09PT0iID4+IHBsYW5zLSREQVRFLmxvZwogICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgY2F0IHBsYW4ubG9nID4+IHBsYW5zLSREQVRF
LmxvZwoKCQkJCQl0aW1lPWBjYXQgcGxhbi5sb2cgfCBncmVwICdeVGltZScgfCBhd2sgJ3tw
cmludCAkMn0nYAoJCQkJCXJlbW92ZWQ9YGNhdCBwbGFuLmxvZyB8IGdyZXAgJ1Jvd3MgUmVt
b3ZlZCBieSBJbmRleCBSZWNoZWNrJyB8IGF3ayAne3ByaW50ICQ2fSdgCgogICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgWyAiJHJlbW92ZWQiID09ICIiIF07
IHRoZW4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
cmVtb3ZlZD0iMCIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZp
CgoJCQkJCXJvd3M9YHBzcWwgdGVzdCAtdCAtQSAtYyAic2VsZWN0IGNvdW50KCopIGZyb20g
dCB3aGVyZSBhID0gICR2ImAKCgkJCQkJZWNobyAiJFJVTglpbnQ0CW1pc21hdGNoCSROVU1f
UEFHRVMJJFJPV1NfUEVSX1JBTkdFCSRtcAkkVE9UQUxfUk9XUwkkTU9EVUxPX0lOVEVSVkFM
CSRwcHIJJGZmCSRORElTVElOQ1QJJE5ESVNUSU5DVF9UQVJHRVQJJGZwcgkkaWR4X3BhZ2Vz
CSRpCSRTRUVECSR2CSR0aW1lCSRyZW1vdmVkCSRyb3dzIiA+PiByZXN1bHRzLSRSRVNVTFQt
JERBVEUuY3N2CgoJCQkJZG9uZQoKCQkJZG9uZQoKCQlkb25lCgoJZG9uZQoKZG9uZQoKCgoj
IG1kNSBoYXNoZXMgKDMyQiBlYWNoLCBubyB0b2FzdGluZykKClJPV1NfUEVSX1JBTkdFPTEy
MAoKcHNxbCB0ZXN0IC1jICJkcm9wIHRhYmxlIGlmIGV4aXN0cyB0Igpwc3FsIHRlc3QgLWMg
ImNyZWF0ZSB0YWJsZSB0IChhIHRleHQpIgoKZm9yIG1wIGluICRNQVRDSElOR19QQUdFUzsg
ZG8KCglwc3FsIHRlc3QgLWMgInRydW5jYXRlIHQiCglwc3FsIHRlc3QgLWMgImRyb3AgaW5k
ZXggaWYgZXhpc3RzIGlkeCIKCgkjIHRvdGFsIG51bWJlciBvZiByb3dzIGluIHRoZSB0YWJs
ZQoJVE9UQUxfUk9XUz0kKChOVU1fUEFHRVMgKiBST1dTX1BFUl9SQU5HRSkpCgoJIyBob3cg
b2Z0ZW4gd2UgbmVlZCB0byByZXBlYXQgdGhlIHZhbHVlcywgdG8gZ2V0IHRoZSBkZXNpcmVk
IG51bWJlcgoJIyBvZiBtYXRjaGluZyBwYWdlcwoJTU9EVUxPX0lOVEVSVkFMPSQoKFRPVEFM
X1JPV1MgLyBtcCkpCgoJIyBnZW5lcmF0ZSBkYXRhCglwc3FsIHRlc3QgLWMgImluc2VydCBp
bnRvIHQgc2VsZWN0IG1kNShtb2QoaSwgJE1PRFVMT19JTlRFUlZBTCk6OnRleHQpIGZyb20g
Z2VuZXJhdGVfc2VyaWVzKDEsICRUT1RBTF9ST1dTKSBzKGkpIgoKCWZvciBwcHIgaW4gJFBB
R0VTX1BFUl9SQU5HRTsgZG8KCgkJTkRJU1RJTkNUPSQoKHBwciAqIFJPV1NfUEVSX1JBTkdF
KSkKCgkJZm9yIGZmIGluICRGSUxMX0ZBQ1RPUlM7IGRvCgoJCQkjIHVzZWQgdG8gc2l6ZSB0
aGUgYmxvb20gZmlsdGVyICh0b28gc21hbGwgLyB0b28gbGFyZ2UpCgkJCU5ESVNUSU5DVF9U
QVJHRVQ9JCgoTkRJU1RJTkNUICogMTAwIC8gZmYpKQoKCQkJZm9yIGZwciBpbiAkRkFMU0Vf
UE9TSVRJVkVTOyBkbwoKCQkJCWlmIFsgLWYgInN0b3AiIF07IHRoZW4KCQkJCQlybSAic3Rv
cCIKCQkJCQlleGl0CgkJCQlmaQoKCQkJCVNFRUQ9JCgoU0VFRCsxMDAwKSkKCgkJCQlwc3Fs
IHRlc3QgLWMgImRyb3AgaW5kZXggaWYgZXhpc3RzIGlkeCIKCQkJCXBzcWwgdGVzdCAtYyAi
Y3JlYXRlIGluZGV4IGlkeCBvbiB0IHVzaW5nIGJyaW4gKGEgdGV4dF9ibG9vbV9vcHMobl9k
aXN0aW5jdF9wZXJfcmFuZ2UgPSAkTkRJU1RJTkNUX1RBUkdFVCwgZmFsc2VfcG9zaXRpdmVf
cmF0ZSA9ICRmcHIsIHNvcnRfbW9kZSA9IGZhbHNlKSkgd2l0aCAocGFnZXNfcGVyX3Jhbmdl
ID0gJHBwcikiCgkJCQlwc3FsIHRlc3QgLWMgInZhY3V1bSBhbmFseXplIHQiCgoJCQkJaWR4
X3BhZ2VzPWBwc3FsIHRlc3QgLXQgLUEgLWMgInNlbGVjdCByZWxwYWdlcyBmcm9tIHBnX2Ns
YXNzIHdoZXJlIHJlbG5hbWUgPSAnaWR4JyJgCgoJCQkJIyBpbmRleCBub3QgYnVpbHQgKGZp
bHRlciB0b28gbGFyZ2UpCgkJCQlpZiBbICIkaWR4X3BhZ2VzIiA9PSAiIiBdOyB0aGVuCgkJ
CQkJY29udGludWUKCQkJCWZpCgoJCQkJIyBtYXRjaGVzCgkJCQlmb3IgaSBpbiBgc2VxIDEg
JFJVTlNgOyBkbwoKCQkJCQlSVU49JCgoUlVOKzEpKQoKCQkJCQl2PWAuL3JuZC5weSAkKChT
RUVEK2kpKSAwICQoKE1PRFVMT19JTlRFUlZBTC0xKSlgCgoJCQkJCXBzcWwgdGVzdCA+IHBs
YW4ubG9nIDw8RU9GCnNldCBlbmFibGVfc2Vxc2NhbiA9IG9mZjsKc2V0IG1heF9wYXJhbGxl
bF93b3JrZXJzX3Blcl9nYXRoZXIgPSAwOwpleHBsYWluIGFuYWx5emUgc2VsZWN0ICogZnJv
bSB0IHdoZXJlIGEgPSBtZDUoJHY6OnRleHQpOwpcdGltaW5nCnNlbGVjdCBjb3VudCgqKSBm
cm9tIHQgd2hlcmUgYSA9IG1kNSgkdjo6dGV4dCk7CkVPRgoKICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgIGVjaG8gIj09PT09IFJVTiAkUlVOID09PT09IiA+PiBw
bGFucy0kREFURS5sb2cKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
IGNhdCBwbGFuLmxvZyA+PiBwbGFucy0kREFURS5sb2cKCgkJCQkJdGltZT1gY2F0IHBsYW4u
bG9nIHwgZ3JlcCAnXlRpbWUnIHwgYXdrICd7cHJpbnQgJDJ9J2AKCQkJCQlyZW1vdmVkPWBj
YXQgcGxhbi5sb2cgfCBncmVwICdSb3dzIFJlbW92ZWQgYnkgSW5kZXggUmVjaGVjaycgfCBh
d2sgJ3twcmludCAkNn0nYAoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgIGlmIFsgIiRyZW1vdmVkIiA9PSAiIiBdOyB0aGVuCiAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZWQ9IjAiCiAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICBmaQoKCQkJCQlyb3dzPWBwc3FsIHRlc3QgLXQg
LUEgLWMgInNlbGVjdCBjb3VudCgqKSBmcm9tIHQgd2hlcmUgYSA9ICBtZDUoJHY6OnRleHQp
ImAKCgkJCQkJZWNobyAiJFJVTgl0ZXh0CW1hdGNoCSROVU1fUEFHRVMJJFJPV1NfUEVSX1JB
TkdFCSRtcAkkVE9UQUxfUk9XUwkkTU9EVUxPX0lOVEVSVkFMCSRwcHIJJGZmCSRORElTVElO
Q1QJJE5ESVNUSU5DVF9UQVJHRVQJJGZwcgkkaWR4X3BhZ2VzCSRpCSRTRUVECSR2CSR0aW1l
CSRyZW1vdmVkCSRyb3dzIiA+PiByZXN1bHRzLSRSRVNVTFQtJERBVEUuY3N2CgoJCQkJZG9u
ZQoKCQkJCSMgbm8gbWF0Y2hlcyAob3V0c2lkZSBtb2R1bG8gaW50ZXJ2YWwpCgkJCQlmb3Ig
aSBpbiBgc2VxIDEgJFJVTlNgOyBkbwoKCQkJCQlSVU49JCgoUlVOKzEpKQoKCQkJCQl2PWAu
L3JuZC5weSAkKChTRUVEK2kpKSAkTU9EVUxPX0lOVEVSVkFMICQoKE1PRFVMT19JTlRFUlZB
TCoyKSlgCgoJCQkJCXBzcWwgdGVzdCA+IHBsYW4ubG9nIDw8RU9GCnNldCBlbmFibGVfc2Vx
c2NhbiA9IG9mZjsKc2V0IG1heF9wYXJhbGxlbF93b3JrZXJzX3Blcl9nYXRoZXIgPSAwOwpl
eHBsYWluIGFuYWx5emUgc2VsZWN0ICogZnJvbSB0IHdoZXJlIGEgPSBtZDUoJHY6OnRleHQp
OwpcdGltaW5nCnNlbGVjdCBjb3VudCgqKSBmcm9tIHQgd2hlcmUgYSA9IG1kNSgkdjo6dGV4
dCk7CkVPRgoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVjaG8g
Ij09PT09IFJVTiAkUlVOID09PT09IiA+PiBwbGFucy0kREFURS5sb2cKICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhdCBwbGFuLmxvZyA+PiBwbGFucy0kREFU
RS5sb2cKCgkJCQkJdGltZT1gY2F0IHBsYW4ubG9nIHwgZ3JlcCAnXlRpbWUnIHwgYXdrICd7
cHJpbnQgJDJ9J2AKCQkJCQlyZW1vdmVkPWBjYXQgcGxhbi5sb2cgfCBncmVwICdSb3dzIFJl
bW92ZWQgYnkgSW5kZXggUmVjaGVjaycgfCBhd2sgJ3twcmludCAkNn0nYAoKICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIFsgIiRyZW1vdmVkIiA9PSAiIiBd
OyB0aGVuCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
IHJlbW92ZWQ9IjAiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBm
aQoKCQkJCQlyb3dzPWBwc3FsIHRlc3QgLXQgLUEgLWMgInNlbGVjdCBjb3VudCgqKSBmcm9t
IHQgd2hlcmUgYSA9ICBtZDUoJHY6OnRleHQpImAKCgkJCQkJZWNobyAiJFJVTgl0ZXh0CW1p
c21hdGNoCSROVU1fUEFHRVMJJFJPV1NfUEVSX1JBTkdFCSRtcAkkVE9UQUxfUk9XUwkkTU9E
VUxPX0lOVEVSVkFMCSRwcHIJJGZmCSRORElTVElOQ1QJJE5ESVNUSU5DVF9UQVJHRVQJJGZw
cgkkaWR4X3BhZ2VzCSRpCSRTRUVECSR2CSR0aW1lCSRyZW1vdmVkCSRyb3dzIiA+PiByZXN1
bHRzLSRSRVNVTFQtJERBVEUuY3N2CgoJCQkJZG9uZQoKCQkJZG9uZQoKCQlkb25lCgoJZG9u
ZQoKZG9uZQoK
--------------45196B023835614BDFCBD16D--





^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/9] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 4e0c9be58c..4099e72001 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8191,7 +8191,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------4B194FF8F3EA3786FF9EAE1F
Content-Type: application/vnd.oasis.opendocument.spreadsheet;
 name="brin-bench.ods"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
 filename="brin-bench.ods"

UEsDBBQAAAgAAOO7Q1KFbDmKLgAAAC4AAAAIAAAAbWltZXR5cGVhcHBsaWNhdGlvbi92bmQu
b2FzaXMub3BlbmRvY3VtZW50LnNwcmVhZHNoZWV0UEsDBBQAAAgAAOO7Q1IAAAAAAAAAAAAA
AAAcAAAAQ29uZmlndXJhdGlvbnMyL2FjY2VsZXJhdG9yL1BLAwQUAAAIAADju0NSAAAAAAAA
AAAAAAAAHwAAAENvbmZpZ3VyYXRpb25zMi9pbWFnZXMvQml0bWFwcy9QSwMEFAAACAAA47tD
UgAAAAAAAAAAAAAAABgAAABDb25maWd1cmF0aW9uczIvdG9vbGJhci9QSwMEFAAACAAA47tD
UgAAAAAAAAAAAAAAABgAAABDb25maWd1cmF0aW9uczIvZmxvYXRlci9QSwMEFAAACAAA47tD
UgAAAAAAAAAAAAAAABoAAABDb25maWd1cmF0aW9uczIvcG9wdXBtZW51L1BLAwQUAAAIAADj
u0NSAAAAAAAAAAAAAAAAGAAAAENvbmZpZ3VyYXRpb25zMi9tZW51YmFyL1BLAwQUAAAIAADj
u0NSAAAAAAAAAAAAAAAAGgAAAENvbmZpZ3VyYXRpb25zMi90b29scGFuZWwvUEsDBBQAAAgA
AOO7Q1IAAAAAAAAAAAAAAAAaAAAAQ29uZmlndXJhdGlvbnMyL3N0YXR1c2Jhci9QSwMEFAAA
CAAA47tDUgAAAAAAAAAAAAAAABwAAABDb25maWd1cmF0aW9uczIvcHJvZ3Jlc3NiYXIvUEsD
BBQACAgIAOO7Q1IAAAAAAAAAAAAAAAAMAAAAbWFuaWZlc3QucmRmzZPNboMwEITvPIVlzthA
LwUFcijKuWqfwDWGWAUv8poS3r6Ok1ZRpKrqn9TjrkYz3460m+1hHMiLsqjBVDRjKSXKSGi1
6Ss6uy65pds62ti2Kx+aHfFqg6WfKrp3bio5X5aFLTcMbM+zoih4mvM8T7wiwdU4cUgMxrSO
CAkejUJp9eR8GjnO4glmV1F066CQefcgPYvdOqmgsgphtlK9h7YgkYFAjQlMyoR0gxy6TkvF
M5bzUTnBoe3ix2C904OiPGDwK47P2N6IDKblXuC9sO5cg998lWh67mN6ddPF8d8jlGCcMu5P
6rs7ef/n/i7P/xnir7R2RGxAzqNn+pDntPIfVUevUEsHCLT3aNIFAQAAgwMAAFBLAwQUAAgI
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
qj3ilyQOPhr0ABLtL3rhZyov0EILLbTQQgsttND+W1rqv9n/cfyPtLu9/1v//Op6vYEY/1mt
W6p3rm9s+rFGaz8x2MF6O6wN/SU0Y2o3tvDifH1Jv4qU7vqardljWAZb3pyj1Tq6spysn/fd
2kTWub1a2+VJvKrVtXjeoiYdYprGsV9fxoqz3RtNUinHrl0haYvWpK6ELiWP4mOcD1bNUlgn
6uNKr69UXetjCoGnpsaut8D1spZC5LSaHJ0d1czXz8RDc7d5Xl9JkXeLGk6noLyv069jXdNk
vHUxiHZKk/clm/mSVvMxB7N+Wwrb+ur8Rl5vV7WKquUlh2kYw5Hzcn1uJ5KV344XmvjGZUpE
Stoq+wVtm/1QsoBjNO341mdqLcsKuza3xemjv4aNbm0aIxcZr6vahaTTlXfDKXC0/hPnbbIh
dLuFtK3JJRedK9LWwkv4dazpvPpsU+lmWzg6OQPk79IYL24UG9bslrl36/rubP6q+62s5Pf9
wHc1PnlNpg9l0CfL+PFzjx2XGxkfGnh7uNz5iO/djLTU957HpfBBL+pD0eqTRd9D7o/6e7y+
FvihAf0zWF0OlqCfvepL4Vohc/xLuiQb8JEHU5ZKK8zje+XvT6sPycePmnz4Ht4L/c7BjvxQ
okqyG1PpV7RJyfVaJ3XoNLfogiEllSAVaYLorhsnctwrZOQlenur3985r7+vxDrOVa7h5t79
g2aV7QOJ5jA3Zp3MfkE78spr5nXxXL0erGVDloocPvFtUd4Zmr3e9SJbgfZzf8nBurVNy3Qo
ye30uaENTd1KTi2JhPxyNutjV2NFaXsgTNKB5lK9tJLLyr5x1OeWrIjnTVJcK7mhyCW72Fil
RVKxeefJNrbtTDT4diYsRe0z70dtfGYwi2RAEm5b7UfOj82tm6eHlvLEeapzuaI957ZIJuBl
gM4pTefcynGfv+dXGCXispx2WSvuXdu8BEn6K6f8lk5tdzJYkhnObZP1/Nj3xHPwzGNa+Sog
s/Zr7b7Z3nVVh6qmhiXLeVvlkNdkzlZiYLWrbqpApuj7RLfd5Dy/acdUJWViard6qGJL9HmW
JnV9bG7H1LflgTDpfshB1wvavEn22sPOR5AlmSP9rHDmvp8P8kI+nxX5WC2UIh2V25Hlo+fZ
MrZt2+/VEs/L1vHg3PIeHhmmXbofb0eC/RZaaKGFFlpooYUWWmihhRZaaKGFFlpooYUWWmih
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
--------------4B194FF8F3EA3786FF9EAE1F
Content-Type: application/x-compressed-tar;
 name="brin-stress-test.tgz"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
 filename="brin-stress-test.tgz"

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
4sSJE/vk/y10LU4AkAEA
--------------4B194FF8F3EA3786FF9EAE1F
Content-Type: application/x-compressed-tar;
 name="brin-bench.tgz"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
 filename="brin-bench.tgz"

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
--------------4B194FF8F3EA3786FF9EAE1F--





^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/9] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 4e0c9be58c..4099e72001 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8191,7 +8191,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------0E72B707603BED22B4040825--





^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/9] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 1487710d59..33841e14f2 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8191,7 +8191,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------22A4B241170149838D4D1F8F
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210215.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210215.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 58fe109d2d..8a1a9da78f 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -389,6 +389,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -410,6 +413,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -470,7 +528,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -480,51 +538,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index d7b55f57ea..871e024e00 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8143,7 +8143,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8159,7 +8159,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------CF71AF65F7C337C37C24B045
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210112.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210112.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/6] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 58fe109d2d..8a1a9da78f 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -389,6 +389,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -410,6 +413,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -470,7 +528,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -480,51 +538,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index d7b55f57ea..871e024e00 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8143,7 +8143,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8159,7 +8159,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------D21F32E0F9E7408E9BE1AF2E
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210114.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210114.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/6] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index d27336adcd..f3ead7d53d 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8145,7 +8145,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8161,7 +8161,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------310A2AE1CC4C2E2E77559E3D
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-suppo-20210114-2.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-suppo-20210114-2.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index b5f52d4e4a..2ef11245a8 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8183,7 +8183,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8199,7 +8199,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------FA974B75A0C3E9CA18CE7207
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210122.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210122.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/6] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 158 ++++++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 140 ++++++++++++++------
 src/backend/access/brin/brin_minmax.c    |  92 ++++++++++---
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 303 insertions(+), 95 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..963b7079cf 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,78 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of
+					 * multiple scan keys. We can determine that based on the
+					 * number of arguments - functions with extra parameter
+					 * (number of scan keys) do support this, otherwise we
+					 * have to simply pass the scan keys one by one, as
+					 * before.
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same
+						 * for all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet
+						 * the criteria for a single one of them is enough to
+						 * discard the range as a whole, so break out of the
+						 * loop as soon as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+
+							/* mismatching key, no need to look further  */
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..a260074c91 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -251,6 +253,10 @@ brin_inclusion_add_value(PG_FUNCTION_ARGS)
 /*
  * BRIN inclusion consistent function
  *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
+ *
  * All of the strategies are optional.
  */
 Datum
@@ -258,24 +264,31 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/* Handle IS NULL/IS NOT NULL tests */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -284,7 +297,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -293,7 +311,14 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
@@ -301,10 +326,45 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all regular scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* Skip IS NULL/IS NOT NULL keys (already handled above). */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
+	/* This should be called only for regular keys, not for IS [NOT] NULL. */
+	Assert(!(key->sk_flags & SK_ISNULL));
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +384,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +444,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +464,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +483,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +518,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +528,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..e116084a02 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -140,29 +142,41 @@ brin_minmax_add_value(PG_FUNCTION_ARGS)
  * Given an index tuple corresponding to a certain page range and a scan key,
  * return whether the scan key is consistent with the index tuple's min/max
  * values.  Return true if so, false otherwise.
+ *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
  */
 Datum
 brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
 	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -171,7 +185,12 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -180,13 +199,52 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
+	}
+
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
+
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +287,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 1487710d59..33841e14f2 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8191,7 +8191,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------6A37408A2C42B5B56C3B3D49
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210303.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210303.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c          | 158 +++++++++++++++++++-----
 src/backend/access/brin/brin_validate.c |   4 +-
 2 files changed, 126 insertions(+), 36 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..963b7079cf 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,78 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of
+					 * multiple scan keys. We can determine that based on the
+					 * number of arguments - functions with extra parameter
+					 * (number of scan keys) do support this, otherwise we
+					 * have to simply pass the scan keys one by one, as
+					 * before.
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same
+						 * for all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet
+						 * the criteria for a single one of them is enough to
+						 * discard the range as a whole, so break out of the
+						 * loop as soon as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+
+							/* mismatching key, no need to look further  */
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-- 
2.26.2


--------------AC3FFB734F56C5F52D422EFC
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Process-all-scan-keys-in-existing-BRIN-opcl-20210305.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Process-all-scan-keys-in-existing-BRIN-opcl-20210305.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c          | 158 +++++++++++++++++++-----
 src/backend/access/brin/brin_validate.c |   4 +-
 2 files changed, 126 insertions(+), 36 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..f9a0476024 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,78 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any scan keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of
+					 * multiple scan keys. We can determine that based on the
+					 * number of arguments - functions with extra parameter
+					 * (number of scan keys) do support this, otherwise we
+					 * have to simply pass the scan keys one by one, as
+					 * before.
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same
+						 * for all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet
+						 * the criteria for a single one of them is enough to
+						 * discard the range as a whole, so break out of the
+						 * loop as soon as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+
+							/* mismatching key, no need to look further  */
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-- 
2.26.2


--------------82D677E9F94AC7574E460205
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Process-all-scan-keys-in-existing-BRIN-opcl-20210308.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Process-all-scan-keys-in-existing-BRIN-opcl-20210308.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c          | 158 +++++++++++++++++++-----
 src/backend/access/brin/brin_validate.c |   4 +-
 2 files changed, 126 insertions(+), 36 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..f9a0476024 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,78 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any scan keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of
+					 * multiple scan keys. We can determine that based on the
+					 * number of arguments - functions with extra parameter
+					 * (number of scan keys) do support this, otherwise we
+					 * have to simply pass the scan keys one by one, as
+					 * before.
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same
+						 * for all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet
+						 * the criteria for a single one of them is enough to
+						 * discard the range as a whole, so break out of the
+						 * loop as soon as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+
+							/* mismatching key, no need to look further  */
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-- 
2.26.2


--------------556A1DC61262AF15641DB204
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Process-all-scan-keys-in-existing-BRIN-opc-20210308b.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Process-all-scan-keys-in-existing-BRIN-opc-20210308b.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow future opclases to benefit from seeing all keys at once.

This does break existing BRIN opclasses, because the signature of the
consistent function changed. We might support both variants (with 3 and
4 parameters), but that seems pointless - the changes to NULL handling
likely require updates too. So better to make the failure clear. Also,
we're not aware of any out-of-core opclasses - there may be some, but
probably not many.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 doc/src/sgml/brin.sgml                   |   8 +-
 src/backend/access/brin/brin.c           | 118 +++++++++++++------
 src/backend/access/brin/brin_inclusion.c | 140 ++++++++++++++++-------
 src/backend/access/brin/brin_minmax.c    |  92 ++++++++++++---
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 6 files changed, 269 insertions(+), 97 deletions(-)

diff --git a/doc/src/sgml/brin.sgml b/doc/src/sgml/brin.sgml
index 06880c0f7b..078f51bb55 100644
--- a/doc/src/sgml/brin.sgml
+++ b/doc/src/sgml/brin.sgml
@@ -464,12 +464,14 @@ typedef struct BrinOpcInfo
 
    <varlistentry>
     <term><function>bool consistent(BrinDesc *bdesc, BrinValues *column,
-       ScanKey key)</function></term>
+       ScanKey *keys, int nkeys)</function></term>
     <listitem>
      <para>
-      Returns whether the ScanKey is consistent with the given indexed
-      values for a range.
+      Returns whether all the ScanKey entries are consistent with the given
+      indexed values for a range.
       The attribute number to use is passed as part of the scan key.
+      Multiple scan keys for the same attribute may be passed at once, the
+      number of entries is determined by the <literal>nkeys</literal> parameter.
      </para>
     </listitem>
    </varlistentry>
diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..743f2a925a 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,40 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
+					Oid			collation;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
-
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
-
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					/* skip attributes without any scan keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
+
+					bval = &dtup->bt_columns[attno - 1];
+
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * XXX We simply use the collation from the first key (it
+					 * has to be the same for all keys for the same attribue).
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
+					collation = keys[attno - 1][0]->sk_collation;
+
+					/* Check all keys at once */
+					add = FunctionCall4Coll(&consistentFn[attno - 1],
+											collation,
 											PointerGetDatum(bdesc),
 											PointerGetDatum(bval),
-											PointerGetDatum(key));
+											PointerGetDatum(keys[attno - 1]),
+											Int32GetDatum(nkeys[attno - 1]));
 					addrange = DatumGetBool(add);
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..a260074c91 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -251,6 +253,10 @@ brin_inclusion_add_value(PG_FUNCTION_ARGS)
 /*
  * BRIN inclusion consistent function
  *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
+ *
  * All of the strategies are optional.
  */
 Datum
@@ -258,24 +264,31 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/* Handle IS NULL/IS NOT NULL tests */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -284,7 +297,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -293,7 +311,14 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
@@ -301,10 +326,45 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all regular scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* Skip IS NULL/IS NOT NULL keys (already handled above). */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
+	/* This should be called only for regular keys, not for IS [NOT] NULL. */
+	Assert(!(key->sk_flags & SK_ISNULL));
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +384,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +444,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +464,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +483,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +518,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +528,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..e116084a02 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -140,29 +142,41 @@ brin_minmax_add_value(PG_FUNCTION_ARGS)
  * Given an index tuple corresponding to a certain page range and a scan key,
  * return whether the scan key is consistent with the index tuple's min/max
  * values.  Return true if so, false otherwise.
+ *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
  */
 Datum
 brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
 	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -171,7 +185,12 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -180,13 +199,52 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
+	}
+
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
+
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +287,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..2c4f9a3eff 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											4, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index c7619f8cd3..cd1eda38ab 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8223,7 +8223,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------D524CD37E77B36A2883A7617
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Move-IS-NOT-NULL-handling-from-BRIN-support-20210311.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Move-IS-NOT-NULL-handling-from-BRIN-support-20210311.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/9] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 4e0c9be58c..4099e72001 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8191,7 +8191,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------4B194FF8F3EA3786FF9EAE1F
Content-Type: application/vnd.oasis.opendocument.spreadsheet;
 name="brin-bench.ods"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
 filename="brin-bench.ods"

UEsDBBQAAAgAAOO7Q1KFbDmKLgAAAC4AAAAIAAAAbWltZXR5cGVhcHBsaWNhdGlvbi92bmQu
b2FzaXMub3BlbmRvY3VtZW50LnNwcmVhZHNoZWV0UEsDBBQAAAgAAOO7Q1IAAAAAAAAAAAAA
AAAcAAAAQ29uZmlndXJhdGlvbnMyL2FjY2VsZXJhdG9yL1BLAwQUAAAIAADju0NSAAAAAAAA
AAAAAAAAHwAAAENvbmZpZ3VyYXRpb25zMi9pbWFnZXMvQml0bWFwcy9QSwMEFAAACAAA47tD
UgAAAAAAAAAAAAAAABgAAABDb25maWd1cmF0aW9uczIvdG9vbGJhci9QSwMEFAAACAAA47tD
UgAAAAAAAAAAAAAAABgAAABDb25maWd1cmF0aW9uczIvZmxvYXRlci9QSwMEFAAACAAA47tD
UgAAAAAAAAAAAAAAABoAAABDb25maWd1cmF0aW9uczIvcG9wdXBtZW51L1BLAwQUAAAIAADj
u0NSAAAAAAAAAAAAAAAAGAAAAENvbmZpZ3VyYXRpb25zMi9tZW51YmFyL1BLAwQUAAAIAADj
u0NSAAAAAAAAAAAAAAAAGgAAAENvbmZpZ3VyYXRpb25zMi90b29scGFuZWwvUEsDBBQAAAgA
AOO7Q1IAAAAAAAAAAAAAAAAaAAAAQ29uZmlndXJhdGlvbnMyL3N0YXR1c2Jhci9QSwMEFAAA
CAAA47tDUgAAAAAAAAAAAAAAABwAAABDb25maWd1cmF0aW9uczIvcHJvZ3Jlc3NiYXIvUEsD
BBQACAgIAOO7Q1IAAAAAAAAAAAAAAAAMAAAAbWFuaWZlc3QucmRmzZPNboMwEITvPIVlzthA
LwUFcijKuWqfwDWGWAUv8poS3r6Ok1ZRpKrqn9TjrkYz3460m+1hHMiLsqjBVDRjKSXKSGi1
6Ss6uy65pds62ti2Kx+aHfFqg6WfKrp3bio5X5aFLTcMbM+zoih4mvM8T7wiwdU4cUgMxrSO
CAkejUJp9eR8GjnO4glmV1F066CQefcgPYvdOqmgsgphtlK9h7YgkYFAjQlMyoR0gxy6TkvF
M5bzUTnBoe3ix2C904OiPGDwK47P2N6IDKblXuC9sO5cg998lWh67mN6ddPF8d8jlGCcMu5P
6rs7ef/n/i7P/xnir7R2RGxAzqNn+pDntPIfVUevUEsHCLT3aNIFAQAAgwMAAFBLAwQUAAgI
CADju0NSAAAAAAAAAAAAAAAACAAAAG1ldGEueG1sjZJNb9QwEIbv/IrI9JqM87EfsbKuxIFT
EUgsErdV1p4Gg9de2U6z/HvyTVt64JZ555nxvJOp7m8XHT2h88qaA0kTSiI0wkplmgP5dvwY
78k9f1fZx0clkEkr2guaEF8w1FFfajxrnJT6QH6EcGUAXdclXZ5Y10BGaQ4NyDrU8ZPC7j2Z
K4biA2mdYbb2yjNTX9CzIJi9olmeYH9ZNo41xTetzK+3XkvLsoQxu6BSrNy1dXqkpADUOPT3
kCYpLKy1doWHKSa/i40Cpnilx+h/Lcy7G03M388WnhG+bHfwyqvRcYMGXR2s4w/q7PDzCMA2
KZJdkt09KNPeTt/329O2iJ4Bp6uzP1EEKOjdh1ZpGWcVvOpXScH6X4I8o1ka0yymxZFSlqeM
bpJyX+ab3S4vK1iwaR6UKvQnEcu279JPzr8c80/br3P3f7Ivi8RvodHz9BU9yxO7XpYPfQsf
lIhGPdRnjbGwrQn9tsgkCtR61TYZ3cy6PQ/ulwwlwCt4sVt46475H1BLBwhD5qoIhAEAAAUD
AABQSwMEFAAICAgA47tDUgAAAAAAAAAAAAAAAAoAAABzdHlsZXMueG1s7Vxtb9s4Ev5+v8Jw
cYsWWEXyWxJ7Exd71929Bdpg0XbvPhaMRMnclUSBouKkv/6GlKh3ybIiv6SoEzQVORzOPDMc
DimTN28fPXf0gFlIqH87nlwY4xH2TWoR37kd//n5V+16/Hb9jxtq28TEK4uakYd9roX8ycXh
CBr74SpgOIRCxCWPiPkrikISrnzk4XDFzRUNsK+arqptVrLbuNwMwxm/HW84D1a6vt1uL7az
C8oc/fNHXdRpHD9yPaXeIMa7dimJ832FD07XtkCqmdQLQN57F+eZWAxtu3IRtABsvjkLMm1F
ixhoqfHUMBY6wwFlXFEL5bt2JmgL2gqTddZXEOdbe5ijro0Fbb7to0v8v+tsOlkul7qsTUk3
3HObSUWtIrVpV3keQ1ezaYP9qN2VDbWh3TS1u5mKGUTMlUJapo5dLJqE+uRikrqpwyyrVisw
8UyHdogj7YHg7atUKkpb3GKux8+ZD86s7j44swoDDrlm5lXMSce4TSPfisdnzA8/BpgRUYVc
2WxV4FAeFK0qTAxd0KS2JNhVGqSkdd0CU80LNeJzzGiwyrUu2lS0725X2VuuPUf33YeKJM63
9iPvHrPO9gDbV0YbqLlttf+WEUAgR262kgsTFZRr96+lLolUC5f2cJAE1RyHQjhBfNMwzK/1
D1Ap//nwPhvszOuKqKAtBD6TkaBz2IypC85MvYaxO9GBQsMPYsCPR4nGucl0Ol6rmdOmMGva
yMSahU03XN/ENk+LR/GzkOx2/DMjCOIcTDqKwCPukyrX2xu/J+B90iyjT8gPa9j8gAIa/lSi
iwvHowJrQa852AezgoOFWxKGBYqAcBPs+IBAMOEwO0R7h/9C/43axcrRdBHpKeTYe5ZMjBJL
djd6hx+Qjxxo2CxdHfVR5HxP/OhxJI3GiY9Hv7UYtkQ5mHx6kzMn5XFWqPSwsI0iN8kVFedE
UhlfNBO77liRB4ghh6FgowUQ2oXskGDGVUANXGigWSTkyBeh3bhYED/DTCQ71XZSzoZRYdOV
i3wnQg7UYl8WmBDROAPx/vw0LrPQIHIgv+zDkkbxUSRfN6omYagq/n1XZSuyEhc/tjNOiTak
zDqt+v1OmqgG+/VNPCUlM1PBIDE6d8a4RDRKnjziy9nWgXYWcQgPIbDJjmp4pjw4zAJ13Uym
k6wjYB1xsFXymOSnLvUdwV9xAsOuV2lv8lHVhdikvtXEQK/I0kE8SO8UDYt8E3GsUV+jENNt
V0zJNnJDnKmwoRELuwl7jtrOjmMMVQbBgnjI1QIXQkfZj2oEb3bXyXSeiR6aBCZgAhFIK/pu
tb9RnIgIp66pbHX5fC0kOtQXy+Bcdcw5rZEZ6gOCrH+m6iAvMbGVNQ6JAzEB/AzvHE9mxBgs
y59qsTDAbf8wVFx4oC6EOYG95KzELsY6xTYX72r6evLuqas3BIYyfkYbuEZHcB1Go0BuPShY
8q42KnmeXotOd9B6gCM7fl0/As4XuDclgWMoPBSkc4lvkXj3Blw2wq/f/ODwn25Tn0JB4CYw
aiWv059thtl33+0B2j7g1KdIMt9xKSxUX9m2AZ+yyN/dPHPQ57v54vRuPm0zwfQc3XxxHiH6
CMAdyHcXg/ju5Xff7QHaiwvRL9fNLzu5uSWWcw3Wuurhyh4s4jclBfV6i1joqRvhE0apfRqW
eJkanTS77qFZVVytYVUrIBjlaiKx5KmzfAMDoW9/3Zan062fxDOjr58dFuTGPQIQedJD5INs
jJQDdPKAPC3wem6BgHp9loHns+9zeHz2WmoMjU9Pmecv2qYtSreFlj7J8pGnsA7eOrjr1ES7
+E8TjlcDZrvtCdcJ9x3yEHTF5XQJ7clhPEzeKl1t195vu1GWR3PWE67A+uByrs76YhdZ0tWe
5azzQbZ6Y/SUv+SekhqbuK4mvuuHTI5ZRlMqP5vQMpzTA76Ts8P3RYX1Z2E/PU/stb0cTAbB
JhX77sY2pHqyLwhGHPt8x6DoFsJ2RLB5spPfgZnbhdmkG7NdgVW6Tj7tT03Qda9xPmTKWt08
/Lbiar/tXIB4gNg6LMQvMrT2hn+A8HoA+Buja4OebfG1zx70WcXXqyHj69Vg8fVqZ3xtndoX
kxeXtr6otRrg+y2lrSdY4D0L+3NNW488r1VW90OlzYs+70/OKazL+DdUWJeDfZCwLl33WWnz
4rDfyfm24nq/vA0g/obS5hOG9t7wn2nafK7Rff+0fdH7S2rnEt8XQ8b3xWDxfdEc3+N2VXu8
i4+9pKdsmk8bZUXVY0OMxufSNeTKr+j71MfpKBKUJvhdUndPOade80Gk3EsEQ34qJ4DS435A
WnPar+kcUt15sIwyOd+V0PY9F6baN50OU/XpGbHm001VZZKuShTZEaYdpv4PRuKSghZTJzUB
YumNBVrRTfYwmjJOSL4Cg+k84LkywUS4CfPydtxi4my4cBHX2luvL1PjSzpzWiSEMPekFShG
k166K9x66z653kP3pLyP9tN27acn0n56QO0/gzTPcmi9mfcd5bgXbylUe9gEve+R+bfIbHxL
y16a2rZpZlZEDvUhcN67GmfFoJrWcahO6wRXyixxlN64uIIRNwqpS6zRq2tD/HSKuTP5qRjR
OKARf6WU+8OA3axXAkEXvQiHqcocYGg+gRzxXR0HVEyMOYz3MliOJ7iflBErGukxDSRbYolL
CFDEaQNFk1B9IfwEeUUUHmqE/0ap1Yt3IlafMW6acox3S38uL2vi6SGH4h2OOMulHUcCJQl8
XUBZLo8Oyr/Q0b1EwNERENOsnXUPCcj/EPP7ZpJlUM5KsV8Yo+z4EUF9VWonJLb8PAuS/XLr
n00TND3NkuHgarWsGGKCnguGBLQ+vpAgcSRf2Hd4ZLA1LDUS2PqtNJ4B2x757Ulhm7XCNjs2
bJb8dFfkIw7b94qOHQ1Upn6chDYvVHvc0UvX+ySPoh8PcWJqqkLh5WAN3IFGvID3h8CbjGuI
au7tISyEYkESb/7djsV+KPGjdFUlLkCDSVvzqAWsXabx+2zAbGCVn72iK5TZsDqDP0VbiR3j
TQKBcTFdLmYkvhDIQ8yBOhfboqZYyBL6Ymm8HyjYGMvreXxFkd4sVSLOKSTlNKgVsyiSXjFX
BzNPu5n5xdgwvxUxvZgvs62I3EAKkBXfmgrNjKuJalaTIRniJ4UoR0E8gKviMBV1X4ZHnSto
A/j3rJt/Q+zSxGWEiMv3f0kLRiDgUkayG3PFDa8MEV6D5fJ6tmxyzmpdYquLq/l1vb1UTV4U
qUJiJw4jsHsMDk0EMyKnYjoz/tkWmfMdAh9xEW84Sm7DDUf0/i9sQsFXzKgm3w6F5xkHvsFY
rjdO5kmFh8KURTrFJ4WCU9v7t/zoqMkBYnDWNyJJWQXJ33CDcUy9fvv27Y1eLkxKgpIpSoAL
7IrJqbq7TS+aK+39D6FL8pA5/Xqi+suVVURQrAqgt4qgV3DcBe3H5CLoFmSnFWTjJ4Yd8TZT
CLQv2HGBvn4d/48T7uZJ4+c3FUAKPRaKpP+WpBAnNBVS4ibkfKZ9B6uvlCgODjCdGNOJZkw1
Yz5eG4Yufw0jkUIQrn8cKYG93azlOduEtWGsplerxfLicnYpDj9Pr0UXK/mbKl3nhkX9Tueb
ymJ6voH8DsJ6ucw3iMtO4stCn0/i+cvC/vJJuFvDxkVGWKSqdf9Zyf13YLyvNToR7Y+UXh9n
9fob99f/B1BLBwgikX6e1QoAALFfAABQSwMEFAAICAgA47tDUgAAAAAAAAAAAAAAAAsAAABj
b250ZW50LnhtbOzdXa+byBkH8Pt+Cssr9Y7Y+AWDm2RVadXeJFXVbKverYaZZ2w2GCzAxyf7
6TuDDcav+2yOzzmZ9J+LJIYZGGD4Mdj87bc/Pq7S3gMVZZJn7/r+m2G/R5nMVZIt3vX//fPf
vLD/4/s/vc21TiTNVS43K8oqT+ZZZf7tmdpZOV8XVJpXoqoXsimyeS7KpJxnYkXlvJLzfE1Z
U3d+Xmder3c3XZbluHrXX1bVej4YbLfbN9vxm7xYDH7+18DO8yp6rAZN6UWhVHqp9Gg4HA8W
AyUq4T0ktP2hqfG4rFYXa/hRFA3quW3RMrmyaH/w348fPsklrYSXZGUlMkntBixFUXH3Ql24
u/nlw4Jb1xQ1x2G1NrswTqm7EFWILXcptqw52N3qxfpwAGyN3cFvtn06KGidF1VT2h4P7sps
2aOtrb6kxN5eW7hbe0WV4Fa2Zbt1H9Mk+3y9G9i5TVGdc1fyWKaezq8clFxzF5NrU2/UHkzZ
NnO9KdK6kUoOKCVbpRz4b/z2dMjz/MaRmwx2rw/dZKz43WSsuluj82L1uK/crmi/BHpcU5HY
yiI1TTIVvFxpc6JUVOTr+WEBR+e9SOWhJxWL1hqdbzK1Y+LC4m21+dESTk+Em/vEHw5smXar
EkoVb6tyb1WebpKtfXzIbX3+Ya/X1qlfiZh/etSFu7WzzSqmgn2AjZRnZ5jZzO3NDrUtErMH
OsXlzeL2EB1t3O0OGw3qQk2NNP+KDrLfq50lHBEiquUVBcLBRzOz/uvjh2635+7R0x5eyiJZ
s6nclT7qzPnq6uXInmP0YD1ogbOrL69UGA12sw9XOvX7V7p+b78vO8OFUf99MzbYNbgctBO0
GSN4WkjyFMm0fP92173ayb3da7sT3vX/WiTCXHjNNa0psErSL830we3KHxLT0ese0PsksvLC
Yv4s1nn5l5Nyu4n93tGibXlvQZnpQaYvl9ukLI9KrJNKmi7zIEzDbN/8nab9RL+K/2xuN6tT
htOkL2VFqye1qcgTVa+u9xM9iEwsTMXrrbtU+kXa+SHJNo+9+qBVSUa9v984sCcl79a+wbXO
vJ8uNlVuEEmkVy+n7eX130dbI3O/Xdm+8bVuZriQblZZv6nZneitzdXFbhOVPZ3P44LEZy8m
c+6aBdpVN0vcF98mynpmhgT+eJJk9QZ02nO9ccW1xhX59qRlZkq3WbtZduKSksXS+DZ840f+
zKz9dpM3JXn5ukpWIvW61atiQ3+k4aM7NtwMCIIXa/j4ng33w+irG65FWv6Bllficl9pJq7M
OIIKby0W5O1q/NP895Od98tU//JpSVT5J5vY2bzdOEYl5ToVX/Z7db9kO9ow9yreKldmqWnh
VfF5s3fDnv3oxztv/j8m/ZNCvf0rc2bX+8asWJK5dJqetRswrJLMuzBzX83OtQPBhVmdShZJ
Zeb67dxFkW/W9d102z8utLBtkb1DutRofzjsHxfa34J3Fnioe0MhuqYQpWkzZy0Ke5Nfv/Ca
65gWm7Q6VcpUOu+adTtEmiwyr8w3hR0BP4h0Q171Zd0eS3MTSaLdiqYT2g68LcS67qd2iJHl
nn3d1FJJQXI3J62Kdln57n0ET2QLO2Aens+wrbFLy9oGlMvC3OR5Ve7p5LD+3bwHuz1msNrU
i/PKMN90h3bur5uySvSX/VnWXs3M7hML0+hld9fU72vsds1xNbvJK1EsTC9KSduz2Z7Ilzq8
PaMOa6kXdXx9MFeB3Az4fxjWf/rdw5FvKnNPSyfbWc+y071qafrpYunt78i7O+q8kD2Ox2Xq
y+PRSM40p55YJr+Zib6/rjrTmpUUq33RXdddCmXvN85Wbsb3VNQtOGpes7jt3rFmeZ0m2bV7
ZqwtsqYN3Zl1/97PvVB5t9wbBewG13f7KT0ehrAna2/nX1l/O/96C06LsKmWdOXqeJez3V5s
8sIcGm93ftgL0Wyyrnplnpoh40k3VIlY5Jk5a+LUq4rjo9zOq8zs4kIPuLcmh6bvzrnjxhwb
cyhbNP3sUPiO9BzWU+Xr4wrwCB59Hx5dGfQ+7+hDJ4//r8OOpi/vl0iZ6uPUx6n/Gqf+BEMR
zlDkdsMxNIFP8OlZfJq+qE8XzXm6R08Y6gAiDJ6A0zeKU/AknJqz1j4N1Z2/f1v5q26q8JYu
KAAFr0DB7LUowE3WdzS2AV7A6xXwCoEXPqwCVsDKBawiYPWyWN3aSuAFvIAXHy9/+Fp6XdXl
Hm9O3xbl7lQ8mwon7y1LyuogDbAAFq+BhT98pjuzyVd+MmanC/nZPj6dKa/psmEgScTPMPDB
52b43AywfZewPdNd3J1hmxnYJGADbIANsLFge64bvDvDFquhwJNOgA2wATYmbE+LqL4UbEr5
8XO8Bw/YABtg+y5he1oa94Vgm+qYQg3YABtgA2w82J4W630h2IJhTBFGbIANsAE2JmxPCy2/
HGwasAE2wAbYuLA9Le38Uu+xDWUsZoANsAE2wMaD7ZmS0veFbaYNbAFgA2yADbDxYHum3Ped
R2wjKUUI2AAbYANsPNjcSB5MpRICsAE2wAbYeLA5kTyYyliFCrABNsAG2FiwjZxIHtSwneMF
2AAbYANsF2FzInkwIynEFLABNsAG2HiwOZE8mMUyEmPABtgAG2DjweZE8iD0pcRzbIANsAE2
LmxOJA+mMT48AGyADbDxYXMieTAVsQzxfWyADbABNiZsTiQPBCmSSB4ANsAG2JiwOZE8iGfk
S4zYABtgA2xM2JxIHsQhjSTeYwNsgA2wMWFzInkghzRVeNwDsAE2wMaDbexE8iCQchwhBA/Y
ABtgY8LmRPIg0HIa4ef3ABtgA2xM2JxIHgRKTqIIsAE2wAbYeLA5kTyY+WbEhk9FARtgA2xM
2JxIHghfRfE5XoANsAE2wHYRNieSB2KqhMSPuQA2wAbYmLC5kTwIVSxHgA2wATbAxoPNieRB
MJN+hO9jA2yADbAxYXMieRCEchQhKwrYABtgY8LmRPIgiAAbYANsgI0N28SJ5EGkVRjjcQ/A
BtgAGxM2J5IH9eMeCMEDNsAG2JiwOZE8iIQKYiQPABtgA2xM2JxIHoixGbFpwAbYABtg48Hm
RPIgCKQfTQAbYANsgI0HmxPJAy1oQnhAF7ABNsDGhM2J5IGBbUw+YANsgA2w8WBzInlAgZ7S
OV6ADbABNsB2ETYnkgc01mPCF00CNsAG2JiwOZE80PUfwAbYABtgY8E2dSJ5YFRTGg/oAjbA
BtiYsDmRPNAxTQmPewA2wAbYmLA5kTzQwsCGn98DbIANsDFhcyJ5QFM9IdyKAjbABtiYsDmR
PKChHpEAbIANsAE2HmxOJA+IdKhxKwrYABtgY8LmRPKAtIENHx4ANsAG2JiwOZE80DEF+FQU
sAE2wMaFzY3kwURPCN+gC9gAG2BjwuZE8qD+8ABfNAnYABtg48EWOJE8IKEDjR9MBmyADbAx
YXMieUChnhKyooANsAE2JmxOJA/CQJLAc2yADbABNiZsTiQPwkhqgeQBYANsgI0JmxPJgynF
5m4UsAE2wAbYeLA5kTyY6pgifHgA2AAbYGPC5kTyYKpiFZ7jBdgAG2ADbBdhcyJ5YG5FARtg
A2yAjQ2bE8mDGclYTAEbYANsgI0HmxPJgzCUWiBSBdgAG2DjwTZzInkQjqQUM8AG2AAbYOPB
5kTyYBrHMsRzbIANsAE2JmxOJA+EUFLiiyYBG2ADbEzYnEgexL7SMgRsgA2wATYebE4kD+IR
DSWyooANsAE2JmxOJA/iiEYSz7EBNsAG2JiwOZE8CIQcR/hUFLABNsDGhM2J5EFAchLhVhSw
ATbAxoTNieRBoA1sMWADbIANsPFgcyJ5UD/ugV+pAmyADbDxYAudSB6IiRIxvo8NsAE2wMaE
zYnkgRiqMEbyALABNsDGhM2J5EE8Ulri5/cAG2ADbEzYnEgeiJGKYjzHBtgAG2BjwuZE8iAI
pB/h+9gAG2ADbEzYnEgeBCFgA2yADbDxYXMieUAzPSXcigI2wAbYmLA5kTwgpWd6BNgAG2AD
bDzYnEgeaEETwvexATbABtiYsDmRPNBaS43fPABsgA2w8WA7/AzxNw2bWZ1GCB6wATbAxoTN
ieSBGbHFgA2wATbAxoXNieSBiJVCCB6wATbAxoXNjeSBNLDhOTbABtgAGxM2J5IHIlRS4nEP
wAbYABsTNieSB1pohU9FARtgA2xc2JxIHkSBmsQBYANsgA2w8WBzInkQTQ1seI8NsAE2wMaE
zYnkgfTJjNkAG2ADbICNB5sbyQNfRxojNsAG2AAbC7bRoSN8y7BRqAPCbx4ANsAG2JiwOZE8
mEkZidcJwf8PAAD//+zdu20DORSG0Zash6VhORw++i9hx0o2sIMbLfYHTgVKhANyyI8XbGAD
WyBsEeVBu8/HCTawgQ1sRdgiyoPd5piGuYANbGArwhZRHlywzWkSPNjABrYibBnlwTFf01YU
bGADWxG2iPLggq1N5QHYwAa2ImwR5cHnoUnf2MAGNrAVYYsoD/b2gi7YwAa2OmwZ5cG5+rJi
AxvYwFaD7RZRHuw21/RsEdjABrYibBHlwedUVAQPNrCBrQhbRHlwwdbnG2xgAxvYarBllAdr
HxtsYAMb2IqwZZQHY53LqSjYwAa2ImwZ5cFYe/3GC2xgAxvY/oQtozxoe2ytKNjABrYibBHl
wXms+7BiAxvYwFaELaI8WL3dDt/YwAY2sBVhiygP1mi9ed0DbGADWw22e0R58FmxSarABjaw
FWGLKA+uFdu7fYENbGADWw22jPKgr9s0pQpsYANbEbaI8uD6taPfwQY2sIGtBltEebDaMQ4R
PNjABrYibBHlwerHPg6wgQ1sYKvBFlEeXCu2ftiKgg1sYCvCFlEe7L6+5m+8wAY2sIHtT9gi
yoPP0+C2omADG9iKsEWUB5/rHlZsYAMb2GqwPSLKg/0ae5h5ADawga0IW0R5sG/ns7ugCzaw
ga0IW0Z58Brn8I0NbGADWxG2jPJgtLO5oAs2sIGtCFtEebDHWmuCDWxgA1sNtojyYK/9NqUK
bGADWxW2iPLgM6XKe2xgAxvYirBllAf7WrO5xwY2sIGtCFtGebD3aUoV2MAGtipsEeVBf89z
iODBBjaw1WB7RpQH/XXBdgMb2MAGthpsGeXBNjAZbGADWx22iPKgPebjdEEXbGADWxG2iPKg
3eb99I0NbGADWxG2iPJgvtZaYAMb2MBWhC2iPHiP0butKNjABrYibBHlQbtfW9EH2MAGNrDV
YMsoD87VPA0ONrCBrQpbRnlwrvf6BhvYwAa2GmwR5cGeWlGwgQ1sZdi+I8qDfV60mXkANrCB
rQhbRnkw92O77gE2sIGtCFtEebDPdawX2MAGNrDVYIsoD+ZtjWlKFdjABrYibBnlwWPN9QU2
sIENbDXYIsqDPRwegA1sYKvDFlEeXKw9t/IAbGADWxG2jPLgZ0qVwwOwgQ1sRdgiyoPz69qJ
SqrABjawFWGLKA/GWH16QRdsYANbDbZXRHlw3q4Vm7miYAMb2IqwRZQHa/VHm2ADG9jAVoMt
ojy4fu3dTakCG9jAVoQtojxYs632BhvYwAa2GmwR5cG1FX3aioINbGCrwpZRHvy8oGvFBjaw
ga0IW0Z5cK6XF3TBBjawVWHLKA9+ni2yYgMb2MBWhC2iPNjP8Rxe9wAb2MBWhC2iPLh+rXdb
UbCBDWw12N4R5cFa/d4kVWADG9iKsKWUB9/tN15gAxvYwPYnbBHlwZ77bpgL2MAGtipsEeXB
BzZJFdjABrYibBHlwf4er+EFXbCBDWxF2DLKg/d8TNc9wAY2sBVhyygPHuc4XdAFG9jAVoQt
ozxY+9ieBgcb2MBWhC2iPOh7rmHFBjawga0IW0R50NscDg/ABjawFWE7IsqDPq8Vm/F7YAMb
2IqwRZQHe5sEDzawga0OW0R50M85hwgebGADWxG2jPKgzXM6FQUb2MBWhC2jPGhzzg42sIEN
bDXYMsqDYx7T4QHYwAa2ImwZ5cHazQVdsIENbFXYMsqDY3bf2MAGNrBVYYsoD3abwzc2sIEN
bFXYIsqDzzc21z3ABjaw1WBrEeXB5xtbAxvYwAa2GmwR5cE62+vYYAMb2MBWgy2iPFijjWYr
Cjawga0IW0R5cK3Y7ofDA7CBDWxF2CLKg2vFdjTDXMAGNrAVYcsoD/q6LzMPwAY2sBVhiygP
rq3o85hgAxvYwFaDLaI8uLairRmYDDawga0IW0R5sHr7OiRVYAMb2IqwZZQHe69tKwo2sIGt
BNvj3z/C/xm2/px9ODwAG9jAVoQtojzorws21z3ABjawFWGLKA/2sBUFG9jAVoctozyYbTWH
B2ADG9iKsGWUB6s/22+8wAY2sIHtT9gyyoNzvZeZB2ADG9iKsGWUB7PfmggebGD7j2H7BwAA
///s3bvN5TYQgNGWdPWiWI746r8Ey5s4sIMJPcDBFvAniwPyit9MXthylAfzvap5bGADG9iC
sOUoD0Yd1VUUbGADWxC2FOXBn6toAxvYwAa2EGy/FOXBB9tW7TwAG9jAFoQtRXnwHH28YAMb
2MAWhC1FefCcYAMb2MAWhy1FeXDNNmypAhvYwBaFLUV58Gy9vb6Kgg1sYAvClqI86H2+o4MN
bGADWwy2FOXBuOacxhaBDWxgC8KWojwY5xxgAxvYwBaFLUV5UEp/XhN0wQY2sAVhS1EelOeD
zYkNbGADWwy2PUV5UN5eX+v3wAY2sAVhS1Ee9HOW4bkH2MAGtiBsKcqD3uY7RPBgAxvYgrCl
KA/68I4NbGADWxy2FOVBOfpdbakCG9jAFoQtRXlQzl4scwEb2MAWhS1FeVB2JzawgQ1scdhy
lAd1rnmCDWxgA1sMthTlQX9nHbZUgQ1sYAvClqI86M8Hm0GTYAMb2GKwHSnKgzbmOSRVYAMb
2IKwpSgP7qf/rN8DG9jAFoUtRXlQ9n5VD3TBBjawBWFLUR7Me13Tcw+wgQ1sQdhSlAfzt47p
qyjYwAa2IGwpyoPvxHY6sYENbGCLwpaiPPhObLsTG9jABrYobCnKg9lWWZ57gA1sYAvClqI8
eEqfr3lsYAMb2IKwpSgPrtb647kH2MAGthhsZ4ryYO2rLg90wQY2sAVhS1EerHO9q4ANbGAD
Wwy2FOXBqGubF9jABjawxWBLUR6MuX7zARvYwAa2GGwpyoPRnNjABjawxWFLUR6Uq5e6wAY2
sIEtBluK8qDcvbwb2MAGNrDFYEtRHvQyn+E3NrCBDWxB2FKUB3OsZ+1gAxvYwBaDLUV5sOpo
dh6ADWxgC8J25SgPnlGG9XtgAxvYgrDlKA/67FMEDzawgS0IW5LyYC7v2MAGNrBFYUtRHsxu
HhvYwAa2OGwpyoPvKjqnsUVgAxvYgrClKA8+2AbYwAY2sEVhS1EejG328W+8wAY2sIHtP2FL
UR60dx5dKwo2sIEtCFuK8uDpY3vBBjawgS0IW4ryoG5jb5IqsIENbDHY7hTlwb23VT33ABvY
wBaELUV5cP/ABjawgS0OW4ry4D4+2FxFwQY2sAVhS1EelK1fVSsKNrCBLQhbivLgbv2oBk2C
DWxgC8KWojy4+webeWxgAxvYgrClKA/ut+/VwmSwgQ1sQdhSlAerzk1SBTawgS0KW4ryYNWx
xgAb2MAGthhsKcqDda22fDwAG9jAFoOtpCgP1lhzObGBDWxgC8KWojxY79yHCB5sYANbELYU
5cE61rt8FQUb2MAWhC1FeTDXetYBNrCBDWwx2FKUBx9rfb1gAxvYwBaDLUV5sO7VlvIAbGAD
WxC2FOXBs8avGVsENrCBLQhbivLgz6BJY4vABjawBWFLUR48Zx+v39jABjawBWFLUR48ta/X
XlGwgQ1sMdieFOXB8/QJNrCBDWxR2FKUB22fW/dVFGxgA1sQthTlQevzGBvYwAY2sMVgS1Ee
9GPe4wIb2MAGthhsKcqDe/Wz+ioKNrCBLQhbnvLAPDawgQ1sQdhSlAdrX++6wQY2sIEtBluK
8mDNv/+BDWxgA1sMthTlwaqme4ANbGCLw5aiPGjX/HWb4MEGNrDFYKspyoM/sCkPwAY2sAVh
S1Ee1D5KcxUFG9jAFoQtR3lwuoqCDWxgi8OWojyobdxNKwo2sIEtCFuK8qCM/r4n2MAGNrDF
YEtRHtQyzuaBLtjABrYgbCnKgz9XUR8PwAY2sAVhy1EePKOY7gE2sIEtCluO8qCMvS+wgQ1s
YIvBlqI8+GA7h/V7YAMb2EKwnf/8R/ifw3aNA2xgAxvYYrClKA9amXsfYAMb2MAWgy1FeTCf
5y5gAxvYwBaELUV58MF2FM89wAY2sAVhS1EezPq0x29sYAMb2IKwpSgPVp3bcBUFG9jAFoQt
RXkwS1lFUgU2sIEtCFuK8mDepRdXUbCBDWxB2FKUB9+JbRZJFdjABrYgbCnKg++vGVsENrCB
LQrbL0d5cPSt2XkANrCBLQhbivKgPuNqBWxgAxvYYrClKA9qBdv/Gba/AAAA///s3UuO5DYQ
RdEt6S9yOSIjYv9LcHZOPKhsOADbyBfoWwuo4YGSuo8CNmBTg63E8mBufnEfG7ABG7BlYSux
PIjHd9+ADdiADdhysNVYHlgszkWTwAZswJaErcTywCxW54wN2IAN2JKwlVgexPTp3O4BbMAG
bEnYSiwPLGJzPpgMbMAGbEnYaiwPRj8agS6wARuw5WDbSiwPXrCdjWuLgA3YgC0JW4nlQUze
igIbsAFbHrYSy4M45jp4YgM2YAO2JGwllgexju0BNmADNmBLwlZieTAOX+YANmADNmDLwVZj
eXDbOn/iBWzABmzA9hG2EsuDF2wbsAEbsAFbFrYSy4P3B5OBDdiADdiSsJVYHvjTrPGVKmAD
NmBLwlZjefA0b4zggQ3YgC0H215jedDaeTOpAjZgA7YkbCWWB95bbyuwARuwAVsOthLLg9cT
23HTsQEbsAFbErYSy4PHzCbfPAA2YAO2JGwllgdPszl3YAM2YAO2HGw1lge//ujYgA3YgC0J
W4nlgVuP3oAN2IAN2HKw1VgezN76AmzABmzAloOtxvJg9J2rwYEN2IAtC1uN5cHoWyP3ADZg
A7YcbEeJ5UF7ZnDRJLABG7BlYSuxPGj7nA8vD4AN2IAtCVuJ5YE1Dz+ADdiADdhysJVYHtw2
n4flAbABG7AlYSuxPLhjDmADNmADtixsJZYHtrk5HRuwARuwJWErsTyY4cN+4gVswAZswPYR
thLLg+kv2Mg9gA3YgC0JW4nlwd1nfzZgAzZgA7YcbCWWB9EtjEkVsAEbsOVgO0ssD2KJHrwV
BTZgA7YkbCWWB2/YCHSBDdiALQlbieVBPGHBCB7YgA3YkrCVWB7EHTM6sAEbsAFbDrYSy4Nm
tjwBbMAGbMCWg63E8qC5rYPlAbABG7AlYSuxPPAtdueMDdiADdiSsJVYHniPK3hiAzZgA7Yk
bCWWB3a5O98VBTZgA7YkbCWWB/c1787LA2ADNmDLwXbVWB50c+OMDdiADdiSsJVYHvgZh7MV
BTZgA7YkbCWWBzZj9RvYgA3YgC0HW4nlga0+uWgS2IAN2LKwlVgeWMTmfH4P2IAN2JKwfXF5
8OElQYTF/H8g+kzMf24JbMDGH8DGF7v+37BhsAEbsKHNxher+Y9sTJ42YAM21Nn4YpP+YQYd
to0VNmADNrTZ+GLx/U+3J8AGbMCGJBv3F3vqn2z0hacN2IANfTa+WCt/PNtwjkRhAzbU2fhi
C/zxbGPlaQM2YEOdjS+Wth9+pKyvHykbbMAGbGiz8cWO9TdnG7ABG7AhzoZaJTr+/iQSbMAG
bGiyoVaJjnhgAzZgQ5sNqUq0b7aPHTZgAza02ZCqRPvxYuOADdiADW02pCrRZ7E26DZgAza0
2WhSlegT5vOGDdiADW02pCrRvvMjBTZgQ58NqUq0n3aMEzZgAza02ZCqRN+bFIcN2IANbTa0
KtGwNrimBzZgQ5wNqUr0fbZBtwEbsCHOhlQlOhc/DTZgAzbE2ZCqROftzRpswAZsaLMhVYk+
l43JfRuwARvibEhVovcx786bFNiADW02ulQleu0jOvdtwAZsiLMhVYneJ08bsAEb+mxIVaLX
+nra4GwDNmBDnA2tStTjDOJy2IANcTakKtFoMbndCzZgQ50NqUo0LNbgq2ywARvibEhVonHE
E9y3ARuwIc6GViW6+2WcbcAGbIizIVWJzsNvu2ADNmBDmw2pSrRvtrGAhQ3Y0GbjXKQq0bA4
AjZgAzbE2ZCqRN9scJcobMCGOBtSlWh43MHZBmzAhjgbUpXoPDkShQ3Y0GdDqhKdjWt6YAM2
9NmQqkT7xQcPYAM29NmQqkSfbnPyJgU2YEOcDalK9NrnwjU9sAEb6mxIVaLRY8aADdiADW02
pCrROGMER6KwARvabKxSleh7k8KRKGzAhjgbUpXou9tgOA8bsCHOhlQlOi9vsAEbsKHOhlQl
+ix8Oho2YEOfDalK1A435+Zy2IANcTakKtEx/TDuEoUN2BBnQ6oSve/ZHtiADdgQZ0OrEm1z
7byAhQ3YEGdDqhK9fY4HNmADNsTZkKpE721e3WADNmBDmo1NqhJ9f8yRSwFhAzbE2ZCqRGOG
BU8bsAEb4mxoVaK/bvfqsAEbsKHNhlQlOsJP45oe2IANcTakKtF4/Vu+OA8bsKHOhlQlGsaR
KGzAhj4b/6oS/QsAAP//7N2JDR0hDADRlvZeKAds038J+dkeIk2kaeKJYzD/YLXRHdMjG7JB
ZwNViY4z+1yyIRuywWYDVYl+v7I5b0M2ZAPOBqoS/Y5EvYCVDdlgs3GiKtE56gw3KbIhG3A2
UJXouHOED+dlQzbgbKAq0dnqiJIN2ZANNhuoSnS8OcNf2WRDNuBs0CrRZz2yIRuywWaDVYnW
auZesiEbdDZQleic3qTIhmzw2WBVopc3KbIhG3w2UJXoaB6JyoZs8NmgVaLPcgSxbMgGm40L
VYmuXPvyVzbZkA04G6hK9Jvu5SZFNmQDzgarEp11+pmjbMgGnQ1UJfqN6fEFrGzIBpwNVCU6
ZmZ4JCobsgFnA1WJzrO2cASxbMgGnA1WJXrVHlM2ZEM22GygKtG1VizZkA3ZgLPBqkTPHI4g
lg3ZoLOBqkRHyzAulw3ZgLNxsyrRvw/nnVwuG7IBZwNVib53vN1NimzIBpwNVCXaRqyRsiEb
ssFmA1WJti4bsiEbfDZQlejd5mxewMqGbMDZQFWi9/tjw0pUNmQDzgaqEr27qw3ZkA0+G6hK
9B3Rh92GbMgGnA1UJfrdpJRsyIZssNlAVaLtjhyebciGbLDZeFCV6B0zmxewsiEbcDZQleid
PzbcpMiGbMDZQFWid8mGbMgGnw1UJfr2aN6kyIZs0NlAVaKtxRohG7IhG2w2WJVozWq+gJUN
2YCzwapEl2zIhmzw2UBVot8FrEeisiEbcDZQlejbog3/gJUN2YCzwapEM/fhJkU2ZIPNxouq
RFvkJhuyIRt0NliVaHPehmzIBp8NVCX6zujjlA3ZkA02G6hKtM3fJsWbFNmQDTgbqEr0rRjD
H+dlQzbgbKAq0XZEjCYbsiEbbDZQlWhveU9/ZZMN2YCzwapEp2N6ZEM2+GygKtFnm9U32ZAN
2WCzgapEnzu27gWsbMgGm42GqkTfiDEu2ZAN2WCzgapE/75JmW5SZEM24GywKtGwEpUN2eCz
wapE06dssiEbfDZQlei8agv/gJUN2YCzgapE5127bMiGbNDZQFWi480ZTveSDdmAs4GqRGfW
lbIhG7IBZwNVic5eZ/hwXjZkA84GqhJdubbyJkU2ZIPNRkdVojGqp0MBZUM24GygKtHY60nj
ctmQDTgbqEo0Zo30AlY2ZAPOBqoSHZEZDgWUDdmAs4GqROOsN2VDNmQDzgarEq268pAN2ZAN
NhuoSnT2Ouw2ZEM26GygKtGV61yuNmRDNuBssCrR97facASxbMgGnA1UJTr3XOE/KbIhG2g2
no1ViT71pv+kyIZswNlAVaKzuUmRDdngs8GrRH2TIhuyAWcDVYnG4ZsU2ZANPhuoSrS/ec1H
NmRDNthsoCrR/siGbMgGnw1UJdq7P87Lhmzw2UBVor9NimzIhmzg2UBVoh8bblJkQzbgbKAq
0T7ymV02ZEM20GzsqEq0R77TbkM2ZAPOBqoS7fO32pAN2ZANOBuoSrSnqw3ZkA0+G6hK9LuA
9QWsbMgGnA1WJTo9EpUN2eCzwapE+48NVxuyIRtwNlCVaB4V6WeOsiEbcDZQlWi06ukmRTZk
A84GqhL9rTayNtmQDdlgs4GqRFeuY+2yIRuygWbjQFWimWsvn7LJhmzA2UBVotlqldO9ZEM2
4GygKtF8qsrvlWRDNuBsoCrRXOsob1JkQzbgbKAq0QzPNmRDNvhsoCrR2lxtyIZs8NlgVaJz
beV0L9mQDTgbrEq0W4nKhmzw2WBVoqeVqGzIBp8NVCWa3W5DNmQDz8aJqkRXrK18ASsbsgFn
A1WJrlznOmVDNmSDzQaqEo2qmSkbsiEbbDZQlWgd66wpG7IhG2w2WJXo7ZsU2ZANPhusSnRf
R/nhgWzIBpwNViU61la3bMiGbLDZQFWidXq2IRuywWcDVYmutcZykyIbsgFnA1WJfj/O+0+K
bMgGm40LVYmOygrnbciGbMDZQFWizxt790hUNmQDzgarEo0a6ZGobMgGnA1UJbqiVpVsyIZs
sNlgVaJbRcqGbMgGnA1UJZq7X0fLhmzw2UBVouPIPl1tyIZswNlAVaJzzxXOEv1/2PgDAAD/
/+zdW27cRhCF4a14AzY4M7w0l9NdXRUEMCxD0f4RmgKiKNZDDWBgTsf/s2zIhjQfePkPCRu/
KRtSlei62mXnoYCwARvibEhVota9dYMN2IANaTYWrUq09268JwU2YEOcDa1K1Oy2c20DNmBD
nA2tSrR75SQFNmBDnQ2pSrRNPYwFLGzAhjgbUpXo+Z4Uug3YgA1xNqQqUQteeAAbsKHPhlQl
erLB0QZswIY4G1qV6OIX45IobMCGOBtSlej5dC+6DdiADXE2pCrR2no34nLYgA1tNlapSrS5
z/0CG7ABG9psSFWibfOLcScFNmBDnA2pSrRdfWI4Dxuwoc6GVCW67VYqJymwARvibEhVoktt
VrgBCxuwIc6GVCV6HG3s9QobsAEb2mxIVaJbt1q5AQsbsCHOhlQlukTzfYIN2IANbTakKtFl
b1Z4KxtswIY4G1KVaKl9qkzZYAM2tNnYpCrRsppXjjZgAzbE2ZCqRMtkrTJlgw3YEGdDqhI1
54UHsAEb+mxIVaJxuOFsUmADNsTZkKpE+3awcYMN2IANbTakKtHmvnQqUdiADXE2pCrRtvJQ
QNiADX02pCrR3XtpsAEbsCHOhlQlerJBtwEbsCHOhlQlultfW4UN2IANaTaKVCVaL31vxOWw
ARvibEhVonXutQVswAZsaLMhVYmeRxvkXrABG+JsSFWiu/eNS6KwARvqbGhVoh5XL7ABG7Ch
zYZUJeolVufaBmzAhjgbUpWo77ABG7Chz4ZUJXqcpFw4SYEN2FBnQ6oSDfNgOA8bsKHOhlQl
ej5vg00KbMCGNhu7VCXqLdbgZY6wARvibEhVor7F4sTlsAEb4mxIVaLH0cbG0QZswIY6G1KV
qM8xc20DNmBDnQ2pSjR6XIOHAsIGbIizoVWJ7rEG74CFDdgQZ0OrEl1joduADdhQZ0OqEnXj
kihswIY+G1KVqN+4JAobsKHPhlQl6h4leL0SbMCGNBvbJFWJxhR7LLABG7ChzYZWJVq5kwIb
sKHPhlYleomb88ID2IANcTa0KtEeG7kXbMCGOhtSlagvMdNtwAZsqLMhVYmGeecGLGzAhjob
epUow3nYgA1xNh5YiT49Hz+4z6+fqH/91D56xujk1v3to1//ePp2fOra188vz+9/I/752svx
5ecPflt+GUNv/4PXD+b7f8V7nN7+7PPrL+P0ZZu/v3z66+nrn/3Tfz6Rv9Cwt+/78vT9/V8A
NmD7X8P2wI71DtguB2wBbMAGbMCWg+2Bpe0dsF2BDdiADdjSsF0e2ALfAdvNu0/ABmzABmw5
2B5YK+dhK5O1ugEbsAEbsOVge2BPfSdsK7ABG7ABWw62Bxbfedisee0N2IAN2IAtB9sDm/Q7
YNt97zuwARuwAVsOtgdW83fAVg/YKrABG7ABWw62B3b9d8BWvHDEBmzABmxZ2IZYHmzBzQNg
AzZgy8M2xPJgc6t1ATZgAzZgy8E2xPLgPBUtwAZswAZsKdiuQywPbD1gI9AFNmADtiRsQywP
tn6cis7ABmzABmw52IZYHvTF3S/ABmzABmw52IZYHpywXYEN2IAN2HKwDbE86MXDORUFNmAD
tiRsQywPysWMp3sAG7ABWxa2IZYH5QpswAZswJaHbYjlwQkbHRuwARuwJWEbYnlgxmOLgA3Y
gC0P2xDLg82tMakCNmADtiRstzGWBz8eNMlji4AN2IAtCdsQywPb2IoCG7ABWx62IZYH56SK
U1FgAzZgS8I2xPLgfB4bsAEbsAFbErYhlgc+x+wGbMAGbMCWg22I5UEch2zBzQNgAzZgS8I2
xPLggK0F7zwANmADtiRsQywPIsLjZ7yADdiADdg+hG2I5UFZrFdORYEN2IAtCdsQy4OyW9QO
bMAGbMCWgm0eYnmwX/ut3YAN2IAN2HKwDbE8qEuvNgEbsAEbsOVgG2J50GfvvPMA2IAN2LKw
DbE8KLP1Su4BbMAGbEnYhlgelM288jw2YAM2YEvCNsTywMJb564osAEbsCVhG2J5YP2Aja0o
sAEbsCVhG2J5YM4RG7ABG7DlYRtieXCeiv6MF7ABG7AB24ewDbE8sOY7jwYHNmADtiRsyxDL
AysHbOQewAZswJaEbYjlQS8ezqQK2IAN2JKwDbE8iMKDJoEN2IAtD9sQy4P9xgge2IAN2PKw
DbE8qDMjeGADNmDLwzbE8iCa774BG7ABG7DlYBtieRDmnbdUARuwAVsWtiGWB+cRG2+CBzZg
A7YkbEMsD44jNnPuigIbsAFbErYhlgfReUsVsAEbsKVhW4dYHvgea3BXFNiAbWjY/gYAAP//
7N27kSM7DEDRlPTrXzjdJJB/CCvJWWPGgLX1UO8ogXGmTlECL/gvYWtRHuT3AzawgQ1sNdha
lAex5CusLQIb2MBWhK1FefAdHlgNDjawga0IW4vyIK9Y4wU2sIENbDXYupQHWyxgAxvYwFaD
rUd5cMZibRHYwAa2KmwtyoMYueUDbGADG9hqsPUoDz4fF3TBBjawFWFrUR7EzD19FQUb2MBW
g21rUR5k5Jor2MAGNrDVYOtRHsy8hfIAbGADWxG2FuXB+8S2pUWTYAMb2Iqw9SgPrtjDV1Gw
gQ1sRdhalAfXEY9hKgo2sIGtCFuL8uA64zn8xgY2sIGtCFuL8iBW2z3ABjaw1WFrUR58W1G/
sYENbGArwtaiPIhwQRdsYANbHbYe5cGeq3tsYAMb2Iqw7T3KgxFXHGADG9jAVoOtR3lwxits
9wAb2MBWhK1HeXDFYoMu2MAGtipsPcqDM55xBxvYwAa2GmwtyoN85akVBRvYwFaFrUV5kMsb
th1sYAMb2GqwtSgPvvvYPOYCNrCBrQhbj/JgRMZPvMAGNrCB7VfYWpQH14zXNDwAG9jAVoSt
RXkwZ97D8ABsYANbDbajR3nw2aArggcb2MBWhK1HeTDzlS7ogg1sYCvC1qM8GO8zm31sYAMb
2IqwtSgProxlakXBBjawFWHrUR6c8Ygb2MAGNrDVYOtRHpxxn/axgQ1sYCvC1qM8OOI2XdAF
G9jAVoStR3mQOQ0PwAY2sFVha1Ee5IgZF9jABjaw1WBrUR5877F5zAVsYANbCbb97z/Cfxm2
8Yh12u4BNrCBrQhbi/IgDq9UgQ1sYKvD1qI8GEtsUysKNrCBrQhbi/Igh6ko2MAGtjpsPcqD
fa7T8ABsYANbEbYe5cExr+nNA7CBDWxF2HqUB9u0QRdsYANbGbYe5cE+D8MDsIENbFXYepQH
kbvn98AGNrBVYetRHrz/XB5gAxvYwFaC7d6iPPjCdoINbGADWw22FuVBnvEK1z3ABjawFWFr
UR7kPrfpMRewgQ1sRdh6lAfbvI+feIENbGAD26+w9SgPtvmc3jwAG9jAVoStR3mQnt8DG9jA
VoetR3lwzJgDbGADG9hqsPUoD7b5GPaxgQ1sYCvC1qM8WMccLuiCDWxgK8LWpTw4lAdgAxvY
irA9epQHy7jGBjawgQ1sNdh6lAfryGF4ADawga0IW4/yIPMtG9jABjaw1WDrUR7MfKRFk2AD
G9iKsPUoD644w/AAbGADWxG2HuXB7s0DsIENbHXYepQHI95nNrCBDWxgq8HWozz4rAZ33QNs
YANbEbYe5cEy1vEAG9jABrYabD3Kg3UMSRXYwAa2ImzPHuVB5pUX2MAGNrDVYOtRHsy8h+0e
YAMb2IqwtSgP5pW38GAy2MAGtiJsPcqDERE26IINbGArwtanPHBBF2xgA1sRth7lwS339Pwe
2MAGtiJsLcqDeOYzTEXBBjawFWHrUR7c88gFbGADG9hqsLUoD+KWD9s9wAY2sFVha1Ie5JWG
B2ADG9hqsL1alAeRhgdgAxvY6rD1KA8eeaQLumADG9iKsLUoD/JmeAA2sIGtDluL8iC2XOIn
XmADG9jA9itsPcqDz/DAVBRsYANbEbYW5UE8XNAFG9jAVoetRXmQRw772MAGNrBVYetRHpw5
PZgMNrCBrQpbi/LgDZsTG9jABrYybC3Kg/eBLYZXqsAGNrDVYFtalAfXEvfhxAY2sIGtCFuP
8uCKPZzYwAY2sBVh61EeDMMDsIENbHXYWpQHuc7bABvYwAa2Imw9yoNtvqaX4MEGNrAVYWtR
Hrxhuw+vVIENbGArwtajPIg8LJoEG9jAVoWtR3nw+Y3NiQ1sYANbEbYe5cEyjmHRJNjABrYi
bC3Kg1zHGL6Kgg1sYKvBtrYoD96wpfIAbGADWxW2HuXB56uo1eBgAxvYirD1KA8iF28egA1s
YKvC1qM82Obigi7YwAa2Kmw9yoN9rtO7omADG9iKsPUoDy4RPNjABrY6bD3Kg2Vsw4ntfwLb
HwAAAP//7N1BjuM4DEDRKyWxndjHsUTx/kfo6toMMFULArMZAg+5QvBgW/wU2MD232FrUh7M
ZdwDbGADWxW2HuXBPvf5ABvYwAa2Gmw9yoNj3pIqsIENbEXYPj3Kg8gtjXuADWxgK8LWozzY
5zGfYAMb2MBWg61HebDP1/iJF9jABjaw/Qpbj/Ig8kjjHmADG9iKsLUoD1bkxzc2sIENbFXY
WpQH54jH7VUUbGADWxG2FuXBOb9gS7CBDWxgq8HWojyI14plQBdsYANbEbYW5cGc6w4RPNjA
BrYibC3Kg3Ob83bnAdjABrYabGeL8uC8Z96u3wMb2MBWhK1FefB9eOBUFGxgA1sRthblwbnP
uG+wgQ1sYKvB1qI8WHe+06ko2MAGtiJsLcqD6xGvIYIHG9jAVoStRXlwnXGMD9jABjaw1WBr
UR7cM8KFyWADG9iqsPUoD95rLRE82MAGtiJsLcqD+HzBtoENbGADWw22FuVBXCuXfWxgAxvY
arBdPcqDa+atFQUb2MBWhK1HefCe63avKNjABrYibC3Kg7mvT7h+D2xgA1sRthblQax8Lts9
wAY2sBVha1EezOPric2ALtjABrYibC3Kg/XOY/3EC2xgAxvYfoWtRXlwHbEP5QHYwAa2Imwt
yoN7i3u4zAVsYANbEbYW5cH1iWM4FQUb2MBWhK1FeXBfMaekCmxgA1sJtuufP8L/GbZcf39g
AxvYwFaDrUV5cO2xDa0o2MAGtiJsLcqDjHxaDQ42sIGtCluP8mBbsawGBxvYwFaErUV5kJl3
uqUKbGADWxG2FuXBlXEOa4vABjawFWFrUR7cEWuaYwMb2MBWhK1FeTC29ZheRcEGNrAVYetR
HjzjNVzmAjawga0IW4vy4BrxHhfYwAY2sJVge7YoD64Vn2E1ONjABrYibC3Kg8ycCTawgQ1s
Rdh6lAeZkcY9wAY2sBVha1EerGe+llNRsIENbEXYWpQHMfO5zLGBDWxgK8LWojyI/HpicyoK
NrCBrQhbi/Ig3mstiybBBjawFWFrUR7Ea81lbRHYwAa2ImwtyoNzm3F7FQUb2MBWhK1FebCe
uTkVBRvYwFaE7dWiPDjfc91gAxvYwFaErUV5cK54Dt/YwAY2sBVha1EeXFcc4wQb2MAGthps
LcqD7wHdD9jABjaw1WDrUR78HdD1xAY2sIGtCFuP8uBauQ6wgQ1sYKvB1qM8mPnQioINbGCr
wtaiPPge0PUqCjawga0IW4/y4J55/8QLbGADG9h+ha1FeXBmPIeb4MEGNrDVYNt6lAeH8gBs
YANbHbYW5UHc+XAqCjawga0KW4vyIK+c6YkNbGADWxG2FuVBHjnSqSjYwAa2ImwtyoO81yOc
ioINbGArwtaiPBj32ibYwAY2sBVha1EejPEFW4INbGADWw22FuVBXpERYAMb2MBWg61FeTDm
2sOiSbCBDWxF2FqUB7nlnSJ4sIENbDXY9hblQY71NqALNrCBrQpbi/Igr4gYYAMb2MBWg61J
eRAj3CsKNrCBrQhbi/JgPtYRG9jABjaw1WBrUR7Mbb3DNzawgQ1sRdhalAf5nmNqRcEGNrAV
YWtRHnzBtqbtHmADG9iKsPUoD/b5ni+wgQ1sYKvB1qI8yMxhHxvYwAa2Kmw9yoMz7nATPNjA
BrYabEeP8mCbjzHBBjawga0GW5fyYCkPwAY2sFVha1EejHO9prVFYAMb2IqwtSgPMnIl2MAG
NrAVYWtRHnwvmvSNDWxgA1sRth7lwTHv6VQUbGADWxG2LuVBKA/ABjawVWHrUR584uWWKrCB
DWxV2HqUB8f8TGuLwAY2sBVh61Ee7HMbrt8DG9jAVoPt3aM8iNzSExvYwAa2Imw9yoN9voY5
NrCBDWxF2FqUB7mNNdx5ADawga0IW4/yYJ+7b2xgAxvYqrD1KA+2kcMcG9jABrYibD3Kg23M
oTwAG9jAVoStR3mwz6fDA7CBDWxV2HqUBzMfyzc2sIENbEXYepQHW97pVRRsYANbEbYW5cH1
jNcwoAs2sIGtBtunRXkQn5ULbGADG9iKsLUoD85z5m3RJNjABrYibC3Kg/Mz179h+wMAAP//
7N3dDds4EADhlixZfyyH5HL7L+EUvSRAHJwe7uARMq7B+EBSs6SwCZuwCdufYHvE5MGRMbdJ
2IRN2ITtHmyPmDyIkfM4hE3YhE3Y7sH2iMmD43ArKmzCJmz3YXvE5EF5nVvRWdiETdiE7R5s
j5g8KFssbRU2YRM2YbsH2yMmD9oyXr0Jm7AJm7Ddg+0RkwfjncvwjE3YhE3Y7sF2PGLyIEeu
uQibsAmbsN2D7RGTB6PnnnZswiZswnYTtkdMHpQeuzfoCpuwCdtd2B4xeVDihM2PB8ImbMJ2
E7ZHTB60V2R38kDYhE3YbsL2iMmD7COHV4MLm7AJ203YHjF5ULeo3Y8HwiZswnYTtkdMHrR9
zN0Vm7AJm7DdhO0Rkwd1j+aKTdiETdjuwvaIyYM6RWm/4yVswiZswvYJtvKIyYNrCH4TNmET
NmG7B9sjJg+yj+GsqLAJm7Ddhe2LkwcfLpSsPWv8PxB9Juc/t0Q2ZOMvYOOLXf8HNiKmmrIh
G7LBZuOL1fwHNube6yEbsiEbbDa+2KT/4QG2JhuyIRtsNr5YfH983mz6+byZbMiGbDDZ+GJP
/eFj9RLvtsiGbMgGm40v1sof2Fh/fehBNmRDNphsfLEF/rBJWXvUKhuyIRtgNuZf/ggINo6e
Px8ClQ3ZkA0mG1/sWH9nY++9Vs82ZEM24GywKtHpdGOXDdmQDTYbqEr0etTbD7CyIRtwNliV
aI+XcblsyAadDVQluh/9qK42ZEM24GygKtE9e6ubbMiGbLDZQFWiR7hJkQ3Z4LOBqkSP9EhU
NmSDzwarEm3namPIhmzIBpqNiVWJjpjaSzZkQzbYbKAq0bpG7bIhG7IBZwNVidaM0a1EZUM2
4GywKtGIvXm7l2zIBpwNVCV6vQI4y4ZsyAabDVQlWnpszfs2ZEM24GygKtH6/vVpTtmQDdlg
soGqRM/Vxu5qQzZkg84GqhItzU2KbMgGnw1UJVpnNymyIRt4NmZUJVqmmNtbNmRDNthsoCrR
ssfazL1kQzbgbKAq0YsN79uQDdmAs8GqRH8ciRbZkA3ZYLOBqkRLlQ3ZkA0+G6xKNONoPq8k
G7IBZwNViZYtFs82ZEM26GywKtFdNmRDNvhsoCrRjFzSxxxlQzbgbKAq0YsNcy/ZkA02G29U
JZojt3STIhuyAWcDVYlebKyyIRuywWYDVYnm9ZMN2ZANNhuoSvRSwwlY2ZANOBuoSvREIzJk
QzZkg80GqhI92ejpzeWyIRtwNlCV6LnWWO02ZEM26GygKtEfJxuebciGbNDZYFWiI3e7DdmQ
DTobqEp0H71Vuw3ZkA02GwuqEj3evddDNmRDNthsoCrR8o63VxDLhmzQ2UBVomWJpblJkQ3Z
gLOBqkSPrY9qtyEbsgFnA1WJ7r3X6iZFNmQDzgaqEt3jZMPcSzZkA84GqhItr5jbLBuyIRts
NlCV6PWYo2zIhmzA2UBVosfSo/pOimzIBpwNVCVaZrsN2ZANPBsrqhKtU5TmKJtsyAacDVQl
Wmv07pcU2ZANOBuoSvRabXi7l2zIBpwNVCVal6jNK4hlQzbgbKAq0TJib8blsiEbcDZQlWh9
xeEmRTZkg84GqxI9Ym27bMiGbLDZYFWiNbbmNT2yIRtwNlCV6HWXqKsN2ZANOBuoSjQzm++k
yIZswNnYUJVo1gzZkA3ZoLOBqkTPtUZklw3ZkA02G6hKNLcTDidgZUM24GygKtE8smeVDdmQ
DTYbqEo0Rk7DD7CyIRtwNlCVaBZfnJcN2eCzgapEo+Vr+AasbMgGnA1UJZr7udrwSFQ2ZAPO
BqoSHXHC4RXEsiEbcDZQlWjP0cIJWNmQDTYbO6oS7a+xhlcQy4ZswNlAVaIROQ1H2WRDNuBs
oCrRludqw7MN2ZANOBuoSnS8ch5WorIhG3A2UJVotrGNVTZkQzbYbLAq0TZ22ZAN2aCzgapE
s48x/AArG7IBZ4NVifZ8Dd9JkQ3ZgLOBqkTP1UaOIRuyIRtsNlCVaI48vIJYNmQDzsaBqkRP
Nkp634ZsyAacDVQlmuHZhmzIBp8NVCV6rTYcnJcN2YCzgapEr3dSrERlQzbgbLAq0bltbZIN
2ZANNhusSnRutVmJyoZswNlgVaJbH90riGVDNuBssCrRrWf3VTbZkA04G6xKtI51eLuXbMgG
nA1WJfpjcH6RDdmQDTQbhVWJLn3r3u4lG//Kxj8AAAD//+zdybHrIBQA0ZQ02BIKB+6Qfwhf
fkn8XnR57+UpuGpANv4vG6xKdF/HdLYhG7IBZ4NViV6RYe4lG7IBZ4NViX7jCbsN2ZANOBus
SjQqvIJYNmSDzgarEp31KUeisiEbcDZYleiTlY5EZUM24GzQKtEIr+mRDdmAs8GqRFc9PuYo
G7JBZ4NVid65R8mGbMgGmY19Y1WiUcsvKbIhG3Q2WJVod7QjUdmQDTgbrEr07OmDB7IhG3Q2
WJXo0U9fsiEbssFmg1WJbi8bxuWyIRtwNlCVaM7efHFeNmSDzgarEv0425AN2eCzgapE86n2
di/ZkA06G6xK9HhXG45EZUM24GygKtHKHu0JWNmQDTYbO6oSjaOudCQqG7IBZwNViVa/qw1n
G7IhG3A2UJVo7O9qQzZkQzbgbKAq0Rx+SZEN2eCzwapEq79uUmRDNuhsoCrRPzYcicqGbMDZ
YFWi1aO9FFA2ZAPOBqoS7dnRSzZkQzbYbLAq0U8cK2VDNmSDzQaqEn3ZOFfJhmzIBpqNA1WJ
9p2f3GVDNmSDzQaqEn3Z+KZnUmRDNuBsoCrRv3dS/JIiG7IBZwNVib5sTNmQDdmgs8GqREfe
nkmRDdmgs8GqRLOPdiQqG7IBZ4NVif5eZXtkQzZkg80GqxL9zTZkQzZkA84GqxIdObzdSzZk
g84GqxKNercpsiEbsoFm42RVorO2NC6XDdmAs8GqRLP33mRDNmSDzQarEv19gDUulw3ZgLPB
qkSzT9mQDdmgs8GqRLtnT9mQDdlgs8GqRK/cwmt6ZEM24GywKtEfGyEbsiEbbDZYleidu6sN
2ZANOhusSjQqy9WGbMgGnA1aJVqyIRuyAWfjw6pEb0eisiEbfDZQlWg9Yw67DdmQDTgbqEq0
5sjhCVjZkA04G6hK9GWjxiUbsiEbbDZQlWit5xgenJcN2YCzwapER15eQSwbskFng1WJ/tg4
ZUM2ZIPNBqoSrWeM4X0bsiEbcDZQlejLxhquNmRDNuBsoCrRmqPHLRuyIRtoNr60SvTrbEM2
ZIPOBqoSfdlwJCobsoFng1WJPuMZPuYoG7IBZ4NViT4jht2GbMgGnA1UJfpuUj7pUTbZkA04
G6xKtH4/2ZAN2WCzgapE6+nL55VkQzbobLAq0ei7HYnKhmzA2WBVond/y02KbMgGnA1UJdrp
bEM2ZAPPxoWqRGs625AN2eCzgapEaznbkA3Z4LPBqkRHf6tlQzZkg80GqxIdfcmGbMgGnQ1U
JfrrNmRDNmSDzgarEv095ugVxLIhG3A2UJVonyuW1/TIhmzA2UBVoi8btR7ZkA3ZYLOBqkT7
WMvVhmzIBp0NViX626QM2ZAN2UCzcaMq0b/Vho85yoZswNlAVaLjjJzONmRDNuBsoCrRcUfN
kA3ZkA02G6hK9H5iTC8FlA3ZgLOBqkTvijm/siEbssFmA1WJ3uNdbXhwXjZkA84GqhK9I57p
80qyIRtwNlCV6JjRs2RDNmSDzQaqEr1vNymyIRt8NlCV6D3fTYpfUmRDNthsDFQluq7aw25D
NmQDzgaqEp0jV7jakA3ZgLOBqkTXXUekbMiGbLDZQFWic2aEH2BlQzbgbKAq0RmZYSUqG7IB
ZwNVia49O7xvQzZkA84GqhJdZ20xZUM2ZIPNBqoSnWfO5YMHsiEbcDZQleh8HInKhmzw2UBV
ovPKGb4BKxuywWbjQVWic8uxrERlQzbgbLAq0c+72vAom2zIBpwNViXa9U1nG7IhG3A2UJXo
GnVEyYZsyAabDVYleubjB1jZkA06G6hK9DnzXB/ZkA3ZYLOBqkQ7utoTsLIhG3A2UJVoHHWl
qw3ZkA04G6hK9F1srHQkKhuyAWcDVYmuo7bwDVjZkA00G8eGqkT726s9OC8bsgFnA1WJ/t23
4WpDNmQDzgaqEp2ZFZdsyIZssNlgVaKbt3vJhmzw2UBVorX3Ud7uJRuyAWcDVYnW0Wct2ZAN
2WCzgapEV9QnPTgvG7IBZwNVic6VGVaisiEbcDZQlWivGnXLhmzIBpsNVCXa79+2I1HZkA02
GzurEk1PwMqGbPDZQFWi14zzcZMiG7IBZ+O/V6L/AAAA///s3dER4zYMANGWZMkSyXJIAOy/
hOj8c0kHO5NtwJ9vaGhJ/IeNjO8wLpcN2YCzgapEn2vtv48iy4ZsyAaTDVQl+rT41zOFsiEb
ssFkA1WJPj3O4VU22ZANOBuoSvSZLxuORGVDNuBsoCrR51g1DtmQDdlgs4GqRJ9z7eHqaNmQ
DTgbqEq0jRjTLymyIRtsNk5UJdqeaNM/KbIhG3A2WJXo8EuKbMgGnw1UJXr/uQLrDljZkA04
G6xK9ONIVDZkg88GqhJtzdmGbMgGnw1UJdpG9OlpQzZkA84GqhL98yVlONuQDdmAs4GqRNsR
9/DlctmQDTgbqEq0XfEMX/eSDdmAs4GqRPsRa9ptyIZssNm4UJXojw1vwMqGbMDZYFWiFd/h
y+WyIRtwNlCVaPvEPUI2ZEM22GygKtHfnhSfIJYN2YCzgapEd9tLNmRDNuhsoCrRfey+3QEr
G7IBZwNViT4R1+iyIRuywWYDVYk+dxzjkg3ZkA02G6xK9PZOimzIBp8NVCV6l8/0yIZs4Nn4
oirR32mjZEM2ZIPNBqoS/V1lkw3ZkA04G6hK9PclxW5DNmQDzgaqEq1nf8uL87IhG3A2UJVo
fV82vJMiG7IBZwNVib6njbucbciGbMDZQFWiPzb8kyIbsgFnA1WJVuy23QErG7IBZwNVieZT
VbIhG7IBZwNViWZ72fBOimzIBpuNG1WJ5v2y4Xol2ZANOBuoSjTPinKZo2zIBpwNVCWa30pP
G7IhG3Q2UJXo70+KI1HZkA04G6hKdM26wovzsiEbcDZQlWhe758UZxuyIRtwNlCV6Bp1hnG5
bMgGnA1WJXrtq9w4LxuyAWcDVYnGVU/esiEbssFmA1WJ7qjtVTbZkA04Gw+rEj0dicqGbPDZ
QFWi+44WbmWTDdmAs4GqRF82ZjTZkA3ZYLOBqkT3yJUuc5QN2YCzgapEXzYip2zIhmyw2UBV
ovsb1zIulw3ZgLOBqkR3z56PbMiGbLDZQFWiLxvN3Es2ZIPOBqoS3SMzjctlQzbgbMAq0Z3b
SlQ2ZIPNRkNVojFr+CVFNmSDzgaqEo0lG7IhG3w2UJVo9OrpxnnZkA04G6hKNMZ72pAN2ZAN
OBuoSjSe97ThnRTZkA04G6hKNNrLhndSZEM24GygKtFYNe02ZEM26GygKtF15g5nG7IhG3A2
UJXoavWJkA3ZkA02G6hKtHL37cZ52ZANNhsdVYlWyYZsyAafDVYlepU3YGVDNvBsoCrR3fJ0
B6xsyAadDVQl+rJxpQsPZEM24GygKtE965OeNmRDNuBsoCrRl43T9UqyIRt0NlCV6I59VMmG
bMgGmw1UJbrvWK5Xkg3ZoLOBqkT3E2FcLhuyQWcDVYn+niD2dS/ZkA02G4NVibZWzdxLNmQD
zgaqEq3ez+ZpQzZkA84GqhJ9f3VM76TIhmzA2WBVoseM6TJH2ZANOBuoSrRay7+vm8qGbMgG
kw1UJVqtH81uQzZkA84GqhJ9f7XNj2zIhmyw2UBVovW0aI5EZUM24GygKtFqbTdHorIhG3A2
UJVonhVenJcN2WCzcR2oSjTXPspKVDZkA84GqhLNIRuyIRt8NlCV6N47t3tSZEM24GywKtFr
7eUyR9mQDTgbqEp0j9yZsiEbssFmA1WJvqeNXG6clw3ZgLOBqkR/pw1nG7IhG3A2UJXo3dfq
zjZkQzbgbKAq0Xuu6J42ZEM24GygKtF2xj1kQzZkg83GB1WJtm88o2RDNmSDzQaqEr3bWt23
RGVDNuBsoCrRezgSlQ3Z4LOBqkTvvWocsiEbssFmA1WJ9shjOtuQDdmAs4GqRPs3cjrbkA3Z
gLOBqkQz9qd8glg2ZAPOBqoSrc++ytOGbMgGnA1UJfqeNo7yLVHZkA04G6hK9I6V3YvzsiEb
bDZOViW6wh2wsiEbeDZQlehadaXdhmzIBpwNVCUavXr6TI9syAacDVQlOs48l39SZEM24Gyg
KtGR2ZYfYGVDNuBsoCrRmZnhB1jZkA04G6hKdD65wo3zsiEbcDZQlWifXmWTDdngs8GqRFvt
ciQqG7IBZwNViUbWcuGBbMgGnI0LVYmuqm8625AN2YCzwapEUzZkQzb4bKAq0RXG5bIhG3w2
UJXofvbaxuX/Lzb+AQAA///snUtz5UQShf8K0TGLmYVFvR8EsHQM9nKWxCyupBI4wo8OP3j8
+8m6UjcNWO68crU6YQ5EuGlu6rpSKn11KuuUBGz8BbEhyiU6uBJH2L2ADWBDODZEuUQnOx0m
YAPYADaEY0OUS3RyhA1MUoANYEM4NkS5RI8LsAbYADaADdnYEOUSHYZygN0L2AA2pGNDlEt0
8pikABvAhnhsOFEu0eInV/AIYmAD2BCODVku0VI8ahvABrAhHRuiXKKDJmxgByywAWwIx4Yo
l+gQShzxMkdgA9gQjg1RLtFi8DJHYAPYkI8NUS7RcZpMycAGsAFsyMaGKJfoERtYgAU2gA3h
2BDlEi0KagPYADbkY0OUS3SK0zChtgFsABvCsSHKJTp4bJwHNoAN8djwolyivStqgNoANoAN
4dgQ5RKdpqlMMJcDG8CGcGyIcolOesqTBzaADWBDNjZEuUSLnVzBxnlgA9gQjg1RLtFpmMYJ
2AA2gA3h2BDlEqUpChZggQ1gQzw2RLlEpwPUBrABbMjHhiiX6JBKHuESBTaADeHYEOUSPdq9
sHEe2AA2hGNDlks0k9pAbQPYADZkYyOIcoke9Jh62L2ADWBDODZEuUT7XOxQgA1gA9iQjQ1R
LtG+J2xMwAawAWzIxoYol+ihjGXADlhgA9gQjg1RLtHeYAcssAFsyMeGKJdof0BtA9gANuRj
Q5RL9JDGYcB7UoANYEM4NkS5RHMZUw9zObABbAjHhiiXaJ+KGeDbADaADeHYEOUSPaqNHtgA
NoAN0diIslyi/TgOeLoXsAFsCMeGKJdoysN0wCQF2AA2hGNDlEu0eDwUENgANuRjQ5RLtPdF
D8AGsAFsCMeGKJdoGkfdK2AD2AA2ZGNDlku0qg2spAAbwIZwbIhyiQ5DOYzABrABbAjHhiiX
aDlMYdLABrABbMjGhiiX6DCS2kBJFNgANoRjQ5RLtPRQG8AGsCEeG0mUS3QopR9h9wI2gA3h
2BDlEh11GUY8FBDYADaEY0OUS/SoNlDbADaADeHYEOUSHfpywHtSgA1gQzo2RLlEx1BKwdO9
gA1gQzg2RLlER0WTlAJsABvAhmxsiHKJjmUyJQEbwAawIRsbolyik5ry5IANYAPYkI0NUS7R
4+uV8MZ5YAPYEI4NUS7RcZh0wVvZgA1gQzY2siiX6JjKhJUUYAPYkI4NUS7R3hWF520AG8CG
dGyIcokSNvCYHmAD2BCPDVEu0ePLHA2wAWwAG7KxIcolehjxnhRgA9iQjw1RLtE+0iQFG+eB
DWBDODZEuUSnQ7EFj+kBNoAN4diQ5RLNRWFPCrABbEjHhiiX6BEbmKQAG8CGcGyIcolOfUlw
iQIbwIZsbDglyiU6HYqDSxTYADakY0OUS3TKY8HrlYANYEM6NkS5RKc0HkY8bwPYADaEY0OU
S5TUxjBmYAPYADZkY0OUS/SoNvC8DWAD2BCODVEuUVIbPdQGsAFsSMeGLJdoX/oCbAAbwIZw
bMhyiaYxj/BtABvAhnBsyHKJVmygtgFsABvCsSHLJTpOdoLdC9gANmRjQ4tyifZDcSN2wAIb
wIZwbIhyiQ6uxBGP6QE2gA3h2BDlEh1VGbBxHtgANqRjQ5RLNIfR9VAbwAawIRwbolyiOY++
x0oKsAFsCMeGKJcoYSP02MoGbAAbwrEhyiUap6E/YJICbAAbwrEhyiV6nKRAbQAbwIZwbIhy
iSY/lMMB2AA2gA3Z2BDlEk2JsDEAG8AGsCEaG0aUS3QaJz3BJQpsABvCsSHKJTr1JeLJ5cAG
sCEdG6JcoimgtgFsABvysSHKJRrdEDPM5cAGsCEcG6JconEcDvBtABvAhnRsiHKJHuLYDyiJ
AhvAhnBsiHKJjrlMBWoD2AA2Pj82vrybpquhfFU71A3dBcP83Q/ffr180N+Nv77/y8Pb+3IY
H34s5fHbr4/3/FfUw4en6/n+eSiPtdM9fPHuowc67+X2gbriT791oPnD337hdEVwuD705frh
DzFPdPx9+YG+/v6s/EK/++GBfs1zUT9fXdMc5n6kzx7vn8qbd627eiz3x7YtsTeHX65unm7O
xqtpKgS8ihvVUZfXx1OzntK7Lzz+XL5s7rX/qWdDv2vMh3x8POg370/dRBeg3mr3Nx+mfjc8
PXxAtfrh27fXv56N5aEScb5754+//F0TKk2fbm6f+a3D3fvG3D7d9OV+CX04m2Faxm/eBPcu
ZJwZP6P7Ofj/4dfe3/38zO+8v9Nv/tA8+r7nGlc+3rj0p1TXvit89Lss+7vqM6mWS/XT4fqp
LKh6eCT+/0AQpj5xpPoznz3bhoe3h9vbuQm/D6Az+MGnx/NWv/jtt/VepUF4/OLx7oubq1vq
qtQh54/e9czfcnh/+93ROFPGsz9lt3pKzF/0lPSP96XsfkZWD3LxA2K8vzca3yxm6wV4fwbr
qWWctE/ejioeiaUSmnL8TMRJqbJMREPq/319O9yr28G9xz/5Cenpr2f99d3djZjWsIeEjzQn
vr45pGuHL/6plP/X65uTGjTncfixNkeFBu3Jr24P6dnD9bE9sUF7cLn+Uperxfn5G1+u17fn
tZfrkwg6wxV09tn8p+u7w+PvPyEZvJRinjsp8wHvz8kc+vqro199dW7ubu8e725pakttOjs8
DK9v1AmnLLHOVtq1TXWHPucSBgmX7+q2PJ5dvf3Jvb4xnn+KQu6sSryLt8TuegmN7nLmXcY5
dOcO1llT34TO6mXH2F2vrvGdzZrXviV21/PnVedyZjVvDt21dTZ0OUTHat4S2wAkur4PZv6k
FiWfrg/fvLmbvvrm++47+98vv+/+8W/73xN6aOe9T9qZEHJid9XOt0CiC34lk4sNmdhOZUrD
eq9C1pGHrHpQg0xifbXXs5lcbsjEdCZ4bbX3LgZlmXTrTGyQSc7m5d51fkomqrMhWJdS0Fk5
6mCsVOioBqkYFdZSudiUSjQpqBRjyF4n55mpRNsgFWvXUrnclIq31kZjkw+a/kMzU/GbUvm8
ov7jSxqOX3Nvp+HO3h7GsYy7DvaxLqZFHk2W2H2lnOliYo5AS+zeYi5FyxZzNXZfMRc65z1z
tJhj9xVzuqMuxZNLS+y+ci6RwDW867vENpFzeW3AdbN0cKfJuRCzCl4ZGnI972TTQS2kgwth
bbzdkAkpM0OyyngdbXCJN0bRQQ2GW5JzaxL7ckMmVZnRgEtKzidnmRqIDmowkSY5Z1/uXeen
ZFKFWUw5aO20DTryZmZ0VINUXpJzm1KJJvtEXcsb5YzdVc6pqF7uXyem4l1ySjmfbUyBWQ2h
ozzkXBs512AcPUXHZZpVMUtyS+y+Os523JJSjdxdw9Ftz9ZwFLuvhoudqg+A5Jy8Y+i+Cs52
yTIrK0vs3gouWCb/ltgWCk6v0fw7P6sFf5qCy1nRuORCNly5rLvQYonJhbUy1sWGTOjmTsEF
5Z1yKTNHWDqoTUFuTVVfbsikirFAGZiqcWlex1VwLTLJ2b3cu85PyYS0mFM2p/ooFquO7wjm
KbgGUzGj/ZqsvtiUSojJGueS0i7xq1ihhRi1YU1XX25KxaVAWlRTFkanzC2Tuk0dDAruGQX3
WQpyuUueWVBaYvcWcikoZkFpjt1XzEUa9njDyhy6r5QjgaEzb/xeYvcVc77zgVuOm2N3bZ+r
VGQufi2xTcScXhtuwywcwkliLhgfSP84q7zPzL5KwvTTirkNmZAu88EkT19rgje8KQod1OKa
xFWBfbkhk6rLsvfaBJuc510S09kW+jrntQXvpXOdn5IIqTJf6z46UO/SLvNkaV2SbSCAjPtI
7zoxlUAzbR9Sjk6F6LhaLja4Ksb6j3SvE1Op/oPoqZNRIlnxAEtHaWi512q5x329cS52/vi0
GM4INcfu7Y2j+RGzFDfH7qvfPKkey6xwzLG7Xl+d+Odvid33+tI5iVyFOcfuPX9wilctnEOb
6LdV/1KctUI8Sb/V1UejVK4uOeaprgc10W+r1ZJNmQTnojLBRGOVYxqfuxaan/Tbmqa+3JSJ
y9kYr4wLPlmeVNA0KjcRcGtL3EvvOj8lk7owSoNC8vVfHRNPVNNRDeqKxto11XOxKRXvlLYh
KUd3C1/0tCgrqtVb/nJTJi4bG5RX1gWaIqAUt6N8+xxVOFJmWTNdGUvs3rY45ZgqaYnde0nV
aOaC7xK7r4rLnfbM67vE7nt9Aw0DzJL/Ertv+1xneIPsMbKJhls1LaVZL6TTNFyqg2vKmaRP
4NbgdAs16sLaMuTFpkxIvSUbvXNOW+bGk0bVxLg+yG7KxGXrtM7BaKUM04+xcZD9k4Zbq1wt
vev8lEyqGstJK68V5cMvwrkWlav1yc7FplS8V1Fb+hGU8Za7NrzNR/bHVNKasr7cloryVcWp
QD8SanA7irh9DVOkyKJ1PIAssXvX4Jxn7jNeYveuwXmmY2oO3bsCZ1JgNm+O3b8C59n7Z2vs
3hU4y/WQLbGftgaXZ62QT6zBGa+Tz3RzaObSUKsa3KpR+2JTJqGuniYTbdaBOb7SQQ3G15dq
cJsycTmlqGmU9fr4ng0RNbg5k/NTMqk1OKtSvSI6ZM/e1tlkS4O1axflYlMq3tI8R8c6OdAq
clP51EW4Tam4lKN2Sln6ZqW5UhRVuBYC7rNU4VKtvDDXUufYvatwNmTmYtYcu3cVzjruWuUc
u3cVznnHLFnMsXtX4UJktm+J3bsK5xJzXWWJbaLkVs3nWs2ygf48SctlZbKl1nmruN7NNlsC
XqjFbcwl0ODkVDQ2m+C5GqhRNW5VzW3MxeWYlPXKaJ+Z+zqb6bnV59ksuZyflEutrdkcQla5
akW2l6xNRW61uHixMRnvbaJ/rPU6KOZUrlFNjjTxR3rZyckoSkQlp70Pmjma/l3LcvzHn58w
TDA7SJNpfrPNF5/hiXbMXQ1L7N41G625j/GYY3df782BvYW2xu56fav6Ucz2LbG7nj+Xu6SZ
j+FZYndtn61r9EwlvMQ2UZqr1nitF0WjT1U0wdlYVYDjTjzaKJoXHoSyKRfbqWqNr1tpVeRO
kumgNnsvVjc6bsrFdMYYHZNP0Sj+TtoWT9rJefVJO0sq5yelUvdfGJ2iMyHX/ZtcbWabrJeq
1aXfjclEnVIwLpjstfHciltscGVINX+sk52ajDfGB5rIKF33n3ONldtWZ6QLzf+bB9yRWvOe
uRa8xO5dwyExxFR2c+zeyi4FvrKrsfsqO09qlynsjqG7nj2vOqOYc9oldl9dFzvF3Y62xDbR
daurddos+sGcpusSKbpIuiR5w5zGNXKOubi6XLcpF9ORRE3OqKRMzswpAR3UwpkYVyu7lxtz
IX2ldNIp+5iZ1VASdi2KbsdXMbzYx85PyqVukdWkgWzd7xwzc7NMo421Wq1PHrYlE6tItTn6
6h5lP+euha574bHFG3Px9JXeWRq5bQ6Wrevw4OJGuu4zPOmOuetuid1b0AXHmynNobvLOe4T
YEP3PwAAAP//7H1bjuQ4suyOBKe/SG4ggVO5//1c9xALuDh9mG3iMFmPicJM94+pKyykEI1O
d7O2ow3kmZhTsEXlhp4Vc3xVcCbjhp6WcqIOOhXf2C1Sbto4X0bKQXkYPVGKxXqX1q4KCvuy
eBqEm6MscZGrCEvhRkqNwWmovGiLlJuVTj+XuIQqK9bcMhGkEjgws6dGxxn2/PUz9vGIC2Wm
Ts++2zStaeCxSl61gQzbvz1kT8m4Z7tlTwtmc7hX0XekaZQ29cReJKOVTNxIeucK+q7nVW8t
t0nL/SLPu65gR//Anu4DUwVV08CeFXUvHxmwz+/GnpV1WTkCx0Vf0LOyTmKTAC4CA3tW2LV4
okDPu4HdIuzmHVgj76A8DKGITyZCXXpBj+LLlj70L89eV7jIRRp6LqSQxb/gULE9tinTkcgl
KlmiK9rZQnR32JlyS/Nl6LrpSNDg8vGISyg0ac1jxx9kQnLDum7HrAPrrHb6Y5GMh0LNnjh3
pSroDPEmXTcvBK+R0Rb3w7KfVEnAlvS86q3r/uPRjfP+d6AUuaFnlRzHXwkqkRf0rI6zNHMA
ddyNPXpvQzt2RZfuG3v27lo+UPDkbWKPd3GCleFNkQelzNubRuZBeRZEUbSFjDMic0ENfq6y
Y1r1q1mNNS4uUjo19coNTDDZNqsxzYZd5JKHX1bIunfQXrEsLq//6KCbGvMMKh+PqLzyxNxY
zSppZVjFffPw7SIZk0pOlXuNpwyscWwav/0ij2KRjLbam1rh2GMKXGp8D+DuUHG/aAA39Dqo
5m7s6bNW/Kj1/Ekr6iB4Q89KuXY5oSXDG3u65OqOxmLe2NNSrhWwCWhgd8g5njc1jdSD8iyK
omg3j/c5tYb6lO2Sc3MblUUuro1KqFJVFoVHb/cYqczPwda4aC2hF5ibUoHvy9ox2D+qcnM9
N6IPHnFJZRZMiolxRiCgtZ8thsZfjd6ukbFMCWFrobeNCZ0j3nFkwDy9M5+LZOLHH7fm1T7n
CieMrc1DvfXcr3XEa6jB+8Aer8s1MPVsYE9X5szBZuyBPV2ZS0MAtDKX2NOVOe3g7ndgj1fm
pMCeeIn95urcCEEoD5MptBdSM9LqfljOzWcP17i41PoaH9CqYLbYtmyKeXVujYs2a94oNHav
sMPNjg0rv3IXvnzGPh5xyfKcMnn8yaxY1K5DdkjT+ejAj0UuJlnLltiLxMMGn7GujQ78bzI8
79BcIxOSNGc6xFuJXw5aanyfse5Qc7+oOicOqvaBPV2d64ba493Y0xU6YXDRH9jTNboKt/Xd
2NM1ulZR+7kbe/r5I7RxbmC/WdSNVITyMKoiXuyx4lKvVhy2Ov7uGt0aF1cX7mKdqBAs6r67
RrfGRasUEY33Qiv40PF31+hGMsIjLq8anTYuxeNrwvNJ99Topkm+PxbJWPzhSpW6WgcjUTbV
6Eqbq7o1Mho7htg3xH85XgC4a8lfWaP7Fns8tIM3cBteQ9smNY4b5BXw4buhp8s3jvpGvaCn
dSZ3XGcm9ui9zYguRouvN/bo92eZBA6+xgf26OeTPL4HW+cHdovOnJuojPSG8jC+oXnLQkie
Bx1N31KfLZo/lqikAWbpJVZMZ+5gvS0v2iIz54d0K1xyhrZIMCELaSYnB2+/NMcbAQ6PuKTN
HUlRy7a+NJY7aY5H0264H4tk4odSGvd4XzNTgU1UdhQP2eZjQGtkjEU8fis5o4W2yL/N8f4C
czwBj+UG9vSxoQsozwf2tLJrBu6WB/a0smvgsNUNPa3rTBjWdYk9retaRQdvb+yWHr+p2wWP
GAd+GOOQbrQ1dj2lEhrrt6VO9dXg7RIXvnpvLZ7T3rUxqutoh39znZZ1PxeplJbigT2UXevY
1nrP4G3ouqmv9uDy8YhLKrTKmROrVFgrWqTa4o0nMtV1i2RCnFbK1sHYYgmceLtF14lPzfEW
yZgQV888Pm0EOzi/zfF26brj5nhewJGpgT19JNeawEfCiT0u6AQ9cr2xpwWdNHQs4saelXTZ
GweOUg7sWUlXL3IweXlgt0i6qdEFj7wEfphjoa1T+uQxkaPJXLpnCnfaUb/EJR4C817EJHQD
g1FFcdGeHIupzcUSl7QuLo2rZsxIAwfTdtkdzyXdSEt4RCXEGYX4sR6bBu0K6tO4akMN9Ssv
lUUy7lVfMw5FmoJG1Ju8VOhfH7KnZNTNWIXS9Q899np75P3hHnmNYh8LrvwDe1bZxWpZ0YSy
G3tW2dXM9gCrHzf2rLJ7+QY+sBg8resa+Ka5oWdVXbsKaq/7gm7RdNMWLB5ZCfwsw8LIVbma
pX5AZzc2GR/Py3QrXDJmrMXWg4W4N7BlMS7aUXKs0xHpzyUufIVMJNPWQmuzwAZ5e9r8pkf8
g8vHIy5pkEfGzZlacfTgJ6/aIurmdbo1MqF9REXjOeuCWlJvEnVM0wmhRTJaXayE2CaKnyNs
rfIe3vjPhzeOG+TFNgR2yEvsWSHHVxO0a/7GnhVydlkDPWkG9uj9zfFaNNBtYE+fqTc0WGFg
T/dyFvjz3dgt3XTTViceeQn8LMciVFWroYTJO/o+3za1MV9p17i4NZfYUcY/DM7k2NEr8tUo
7iIXbTn02bUbEejfsW0Ud5qVMrh8POKSU7XOr/hfCu0AV4K2OOXRfN57kYypFskGVOsFNR37
fqe8RTLaaujsUKXOHX3M3k55f7BTXqzkHXvL39DTx661gK0/A3v62LU0dAznxp7VdC32Z+Ck
9cCevb9+VQdDjgf2tKarFbTdfkG3FOimxhc8khL4WYBFSM1OUtOchgpsrrIlwKLOD8TWuLhJ
Jy1qQQpM3Ns1hzvtb/xc5BJCu5OxVRVBHTd3zeFOQ1IGl49HXFKbWeMqsWuIZw0fkNghT7lN
vY8XyZhlEVhZ4+44PCDx3XO4i2TiZy8lNg+mhdEWnL91Dvfv9sprV+xDQK+8G3u6QNcNFCMD
e7xAZ+A45MAeL9AVcOP/gh4vzxX07t7Y01KOOpqxcWO/uTw38hL4aY6FVurdiM3ApWmbmJuX
59a4uHXpltWGomC/+oHy3BoXbVqk1NqaE5jlvifIIsTcvz1jH4+45HxD711z21Ae+B7vccqb
a7k1LiZ5PsnN3BnNN99UnfsijWyRTGzQK7HEyiO1gHNE78PWP9opj8HyyA09veRrAfd6A3u6
OicFbO0b2OPVOfDTJfJ4W2RHR3Bv7Gk5l6OUqJxL7Jba3LxbfeQl8MMci9ibC2tXMnT+MC/6
Zjm3xsVDycWPSLkVuOi8Sc59UZtb46JeG+W0bnXY7m9PaW7qKvfzEft4RCVLc5wSW7gXedXK
zh22iszrv2tkzOMtXUpo3tq4wnLuu0tza2SyNGcubG7UYPPCv7M0x99hkQeag50OZUAlyYY3
4wbp+4ts+xj0aL+hpyuZVMCRv4E9Lnz5gfDlw8JX0k8XtGob2KPfn6UrAvg+Htijn0/qxWDT
xg3dIn3nPf0jW4KfZUt0aVqsSvde0VfitcWC8AvfviUuchWqWS/jUFraMVWyy7dvWv37XOLC
FzfNMW1Ps2u0oH/taGwJ7Tu3EBrREo+4hMJKfxeX5qaK5gvTlr32V759i2TyeL2Icd4eUlTI
7/F3mdZlPxfJmOSkVW2tFO/wrmStLvu7a9//Kt8+btjCOrCnhV3s9+Ej6sSeFnatG27z0td8
LteFnV6lVXDTdWPPCrtyiYObwoE9K+z6VQQs+A/sFmk37+8fCRP8xPs/djzp2mXdyaijQdfX
jt/SlyPBK1wkw8EL3R3xaPtFXrSlqjk3VVu7L1LiiXbLLj0Gjw/jog33JaTd3Epo5Es84pLF
s9C+hYVbBRtBV+cU/iHs5ruHNSo1889iF5QqtYEjjHHVlgmSaYX2c5FM/k7i56LSu6G+36sV
2rew+x2M+wgslQzs6XPComBT5MCeV3R4xkY7nbERKi191VFFl9izik4vaqDBywt6XM+Brl03
dIuam/f2jyAHfhbkQMKVJP4pL/MYTMxtOaL+wrNvhYq8fO7IY431YmA5SLYY3YWYm49qrt0W
yVP2ENi119YOi7m5h9BIcXjEJYSZxF5GLW4L1YrX6XaUtorNfi8/Fsl47cGHrRfpCs/Q+p4K
6nzLsHhnemneQ6AGHSqoneJ7IHibnPsVdbpQat3BVX9gT6u65nj3V2LPqrp6WQXthAf2rKqr
eWYOqrobe1bV+UUEJjAP7NHPpyVXX0y1D+wWZTdt9JcR5SAPoxyK18rcObQdw1EOe+p0U2m3
xCW2bs1juY0VsAYl2I55RyxFnU5sfy7eFzEyVRWv+G3ZEzY2Nf39+Yh9PKLyMv0V0k7V0/EO
NhTZYnbXpgG9i2QqkXItOetsDfRUzKt2kKnTGOhFMlbcM8ellJdfNlqoeyen/cfK7rxznzN4
KjewZ9VcrJCEuoDc2LNqzuI7AZeUgT16fznt60G1NLBn769dFayC3dDTewntaDPnjd2h5WTa
5i8jwkGeRWsIvQpbItUcdMjNi3ZouTpfZ9e4uDZ1jx967QJajm5zeZk2+S9ysTxA7i29Xryg
Q85rPf7/EHPTaaXB5eMRl5Bl7J5W31kNgktBe/rP/u0Re0rFlCqHmms5Fwy6Im2aC2aaloJX
70tPa8iuafXN4PT5u0j3R7v29QbW5wb2dB8dKToZfGNPn7oWsOf0hp7Vc/H+bw3Ww4k9e3f9
MkH15o09+/k0Fh3wQOwF3aLnpq3rMuIb5FmshogyeW1WQ9TBem7PZPDUIneRi2vmi3WhkA3g
ayEv2qLnpoHzi1ysUKEszmkT1IZ5R9pJyLnpBM6g8vGISggA7Z1MWial4em3OyJ8MqX2X56x
p2TMhJpQ6CAxdVjQ7SAjfXrqukqGenxF8c94ytDhKFp8zN6C7lea9tWrCjhlNbCna3OoNdcN
PV6ZQ2fUBvZ0ZU4FrS3d2OOVOTROaWCP1+Ya3r2Z2C1abtqrLiO7QZ5lN0g8eJZRB8XcUNO+
HZGkX9bm1rh4Rop1z/M8BQ8VDtTm1rhYVhiZ1GKNBSXDttrcdOZmcPl4xCVrc42astVGVPFG
re+dDv2xSCb2jCXUHJc0YgaPwDdV575ooVu9M/GIlV6kSuEKTp+9q3N/tGufgPWHG3q6Npc7
PrQ2l9jTtTlRtOBxY89qOk7rbPj7S+zp6lwz8C0zsKerc5VA38OB3aLppi3rMtIb5Fl6g5ia
UyMPKQTXtLbUGr+qz61xcRVSqkRdcSuWTfW5qRHzIhcrxUKcdm+1wtZ9mwp08xrwyG54xCVL
bZneS57RGui8yib7kjL1IfyxSMbijyt3il2awZ2AW6z7pM53DotkSvxheuWdONwJ+HcW6OQ7
rPvAqsmWl9C2YY3jJnnoOdcNPV27yeRNtHaT2NM6kyvobj+wZ3VmvwzNWx7Yo9+f9gttgb6h
Rz+dpK0heEY9sFtU5rx9fsRKyLNYiVaaFbbM+jDQjjsu+mYnlSUu8RN3NpZWxJnA4ai8aIvK
nDfPr3Dhi4U9npmmFEIT9cjbUWujMh3vHlQ+HlF5NfWVWvIQszVT9OB0U+FwaqWySKaWVP1M
8bshtHU0rtoxFf1yXP3yIXtKJn4tzMS19qzqwtFt7wmNXXLuV3nkgecqN/R09aZ3dPL2xp5W
dbFgwnYqO/b9z4yPGa19DezRb8/oYtC+9oae1XT14gdDy3sSP6Yr1P/ISJaQZ8kS8czF+7yo
eWugdMiLttQN58d0K1z46k07ey1kjcCBgLxoh6KbzjZ8LnLhwmoUz7SHCoIl3Z664XyuewRL
POKSjX3NmNN9xN3glIwtjX0i823DGpkcUK/ZbuANnqDZJeloLunWyJhYqx7PGWn8at62x8ft
VI6u97VnoRh7mQzsaTXnDrrPDexxNYf60AzscT3HDAdZJPasnuOrMXiWPrCnFZ0p6sN2Y79Z
043IBHkWZRGaTkr8PxMgBO0j26PpvvBRWeEiVxEuFKttL94wSSd7Aum+KtKtUAl1xtaFvfXa
O2jdvKtKx/Px7pGX8IgLXRJCuxWR2lwFbu/b0Y8d3+K/PWNPyXhwiAesU5fq8CTxjubj7Cj8
l6fsKRmtnNEvWrKAWr/X4eYt6X4jhzywSndDT/eAKdjHc0PPqrpcycHz/YE9q+rkIrhKd2PP
qjqJWwaq4oE9q+pavKo7aMF2Y7eouvl45EhLkCdO9iHQGvXWWyiIyqDxcV70zWevK1wykEJj
HbfuISHAquOuFIuppdznEpdQaCTp4PyKKSM0XWSHiXPIunmH30hLeMQlZEDhSqVnNTgeNrjD
b0fZkXV2Y34sknGvnaVWESa0JzbtkneUHb+YDVq8M00sDRjry+0PvTFLv/63qvu17niG9oEN
7FktxzkNDh5I3Nizas6uWFbgGdzEHr2/5XVIDja139iz9ze+E3D28Iae7uIsHSydvKBblNx8
NnJEJcgTE/tysWm3blo0tBw638DfPauxxsUlPTsKBRN0NHrXrMZ0ZvVzkYs2764hGBQeCSqb
Qrym2Wo/n7GPR1xSk8XT1cWVqT2Y1dih5L6av10jY1LFiqvHD6eBv5hN87cyzc39XL0zaXBD
WQoOmQ0nkr3nb3dIuV80fwtW+1/I0yeuijYMv6Cnz1uzzxw2xrMdv/iHfiro6PILerrqCvZA
BfC0imug3+EN3aLipo3qOlIR9IlhfQiy2I0XD40Zb/OCuqjwhm+6vB66/3uBXeTixhl77p1E
0M3JLheVWbfZ5yIXrY3JQvxkkxY6o7LDwz1U3HSqe3D5eMQlhyHM3LWQUEfHh3cFkc0t8RbJ
xOu511aqxc/FGto5t8USr7RpPW71znSXJtxaPmd459xS2fet4n6xJV4DRcjAni7IOaOmaTf2
eEHOQeODF/R0OQ62ZXhBjxfjioIK88aeL8eBIvMF/WYhNyIR9FkkArul0Ui33tFz7G1CblqO
W+SS5TiK1bVVxQd0v7sct8gldbV06VVVYG/jTeW46cHq4PLxiMvrYFXJuef5fQHf1rsOVqdT
Az8WyVi6GteiElsGxu2Ad6hSpqkd3uqdiQVbS7FMJShgD9W7HPdH2+EpOrc3sKdLcl1RPXdj
TxfluKEHrDf2dFGuMlrTvLGny3KtoUMuN/b080do2scLukXTTUcOdcQi6LNYBI776sStUwXP
iw/U5taouJG5UCy6jfG0iu+uza1x0dpJxamG3oZTRPbU5uYOx4PLxyMuWZurvZOQlDwt/m1q
c2tkzIxq1SJWM7fipBveV7W5xTvTq3QvasylVJjMX1mb+xY3vAIOGZYdA4Z/sB8eGtN6Q0+X
bhxd5l/Q4yITDdJ4Qc9KzLhdCn68gT367Vm+mQl79Ab26OcTv4qi1ik3dofI1OkQpI68Bn2W
11B7dr5ZK60R7p2yJePWp05lS1zkKhT6shW3XgthS2ZetENlTsNUP5e4pA1Kq967NlXqYPLe
taOPmomnjouDy8cjLqky2bhXa3HL0dT0vGpHrW1qH/ljkUzc6njIJOSyKIMl3bxqi2Se9vEt
kkl12TMFRl/T9m87vNNq7hfZ4TlqoTKwp08MvYDDjgN7Wti1AvbMDezR+yt4S5+cb+lLsWag
8BzY08Kuu4Gjyjd2i7Cbn9aN0AZ9FtrQCpOlZau2Dm7h8qItwm5+WLfCJefBXZzVao91Fx61
3cHli1HbJS58ld7IvFYN3Y2W0HeN2k5NegaXj0dcshBYayWn2oIRSCat9LYcok7DNBbJVHYh
Lto7czN02mSLsBOfnwivkXmNM2kvrCpE6IDG2vH2W9j9DqZ44BN7Q0+fxrWOjtve2ON6zkD3
/IE9XarTisdWJPasoku3MvD+DuxZRVezPQ53Od5ieZiji9PVdgQk6LPgiqotvfCqSrzTUfOU
+s2WeEtc4iFIM900X6PWwdOtvGiLopsf1a1wyVJdCLrCTZgUDOHaZXNM856DkY/wiAtdUvNs
253NyUGpnVftUHRz85RFMmmekmYj7hb7ILTHb495yhelujUy6k2JO3vxSvCB8NsTb5ui+xWl
ukYXoZFQA3tW2tWLHPSLekHPCruabb64K57s+PaeFOo4ljTw8w3saWHXCRylHNizwq69jMtQ
V7zEbhF28wnJkZOgD/MrRJrUtJGDTXXzom8u1a1wkYuqcivUcrIQ9TreMZFU6tSx43OJSvze
auslxEPPUzI0imPHWUnp0964n4/YxyMuoQOoaG89PUhqA9sq8qotum72e/mxSMazv49i98DG
BcwN36TrmOYTQot3plYyKtVKv+uAb1e8Q7ruvCteBecgb+hZJcdXvLPhEdzEntVydjmjRmM3
9ujdLT12aGCg4MCePlRvFdRKA3u6l7OgC9PAbtFy816nEZCgz3IrWC3+Z6HjQs6hx66bfPHm
6+waF890+VieiBmdRipbIgW+HMRd46ItA4lr7bFHBsc9tzmqTF20B5ePR1xSllXr6rVYKxUe
2thjizcvBK9xsQx5qLWV0ECi35ve9WAOd/HGNEv/gkLZvAn+Yt5zuH+wLV69Yh8CGx0n9vTJ
ay2ghcLAnj55LRVdWW7s2ZPXfG3CY7h6uk/Sr4p+ewN7WtLVDpYPB3aHpPvCW2WEI+iz0Ap2
jmW2Z5GugHWgvOibJd0al5B0meDVJN5F8FDxHkkn89V2jYvWbDwT5tLA7oOyeB72YA53JCM8
ovKaw6WQQBqiIcPpT87hyhcTEmtkzIlaCw0kNRQdSubb53AX70wPJRevzhB1OVr8Xz2H+7d7
5DUCCxADe7pA1x31Ubuxpwt01sHvb2BPF+gM1po39niBDmxSu6HHy3Por2Ngt2i5+UI74hH0
aWyFebdWuIV2QEXDt2u5NS4ePHrveUzZwBD3bVpu3t20xkVbqeTeC/cK9tBtK8/92zP28YhL
lue6meRMdWgruPd+U31uPhWxRiYDokNid+V4YYNzRLtiK/p89mbxzrySB3u2GmoBq/Pvs9Y/
2iePOxpEdmNPr/kq4ED8wJ6uzwlY/7qhp6tzogJ+ezf2eHNkJ7D+dWNPa7qOOsC8oN974Goj
KsEeRlho7M9Zmsu9+/8tDlwXubhTcfdWqSv9LtW5RS5aQ1k1ZpJK4GjorvLc3MBkcPl4xCXL
c4UtRJCIFJTMJgOTL8pzi2TMKTS21ZB0XGER9N3ludU70zPll6hp1wJnyv6d5Tn+423yHkkT
UJZseDlu0L+/yryv4T4viT1d0SQBYx0H9rj6JTy6LbFnK5qkV+xmwQ84wEe/QSuXNXD/NbBH
P59SelZiT+DAbtHAUx8OGykT9sT/3y8taVrBscOxAobS+RZ58tVk8BIXuYqLUYYZMIGzMHnN
Fgk8LTctUeErdibdS3OTLJ+BAySbJPC0CWJw+XjEJX6bhXrGcJBIB9/ZedEOLj6N4l3iQtlb
b1xT/sau0dAQtx0+WfFXTo0iF8lYI+ves6Sp+GTPmgXI766A/5ss/CqYcH9DTwu7WtDC1409
Lewa2p47sIeFXfylFR12GeCzwk5yOhIUdjf2rLDTKwMNMGF3Y79Z2I2sCXuSAhB7CvF0r6Au
maEKCrsdU+JfCrsVLi/Llyax5EqPnRLor7jJ8kXmZacVLpx5JqpdScwZtOLhLXkmoeymli+D
y8cjLiHSJH1kQjo4K6O2QluC0GhadP6xxCU0mjN7xu21ksG2qLLbUdt8HZR9+ZA9JeNKjTKg
W2ITAUZU0mIQ4lvZ/QYefooO4A7s8Q4wBathA3ta1HXUDGRgz4q6QldDD8Ju7FlJ51dBfY8H
9rSk84bOWt3YLZJuOrxpI9jBnljue6ZUWbzUW+WiFa3VbfGY1joN3FjiIpfEauul1GyQR7NQ
rh1dGCHpZvflc4lLqDOVoFGNuxS4WLcjdThk0DTUZXD5eMSlXNLVMnKD0xAMjduTHanDPJXa
P5a4hDijPOEtZtK8gV5jcdWebsp5RXiNTGwXpAoXltZR47TVs/e3pPt9TPyKgcpuYE8ru6ag
ffTAnlV29TL08w3sYWXHV+8NLNcN8Flt1y8xcLhkYM9+vleUAKg9b+w3l+tGtoM9cd33S5U4
w3qFCM2G8y1xCKHtpkZ+S1xCpjUOjcqmwg1Mhs2Ltmi7qfnLEhe+WlUPPeSuGjoC1HZty0Hs
1JXw5zP28YhLyemSUKlVyLKLD+2r3HMQOx0uWeKSR6oZUcNkmaYGnvZvOogtZTrCtEjGX+bM
LY0oCT2ci6vekRv/sbY7b+TnaLz8wJ7Vc7GXQ8ciXtCzas7imUfTNm7s0bsrLRQueNY2sGfv
rl/U0TrsjT37+fQqaEjXwG7RctMpThupDvYs1UGb5oRHc/UCzmLwlonU+FvnR68rXHJEJP0c
zbs4GtRStvjlljp14/lc5GJxW169TjVWWbS2tWUedX5c+fMZ+3jEJWv81tMAT0RZCT3h21HY
jm3KXMytkTFthUvsHWuxCk9i7DgTF5s31S1yIZfQ2VabddQniRbbHd9a7jcw8msXoScYA3u6
o45Q0TSwpw9ff2sjP+mxPUOTIm7s2ftbLzbQPXpgz36+NOzB3WkSu0XUzbvYR6SDPYt0yKat
WKNCBxGBh69x0Z5h4RmXH0tcQp81tVj6iuVyCw8L7ynQzXrQPhe55ORPcUtf4wImHZbFHvZ/
iLppmsvg8vGIS8ozFVYnU3OFh4W3iDqu82HhNTIZfxJSsXSn7uALNK7aEqHG00CXVTJxX7JX
gS32QuBg5DsU98/08quKzvXd2OMVOjQQ9wU9XaGz1uGojcSevbtySQWtqAb27N1tV2yEwQrd
jT1eQURPgwd2i5ibN66PSAd74rbPV20h5e7mIPS0NS/aIuZmXH4scSlXo6zPaanU0ez5vGiH
mNN58WSNi9cipYsW6h33Jdxz2jp3fhmJDo+40NWpxYZBlTz2NOBIW1y1p/tsvmNYI2Ot9R6r
iXqzVyobpn929AWWPvcXWiSjVkvOR1T2qrDL9NJe7i3mfg8vvwqeew3s6RJdKA24RJfY0yU6
PJHqxp69vznTgpUxbujRb09itQXfmDf07Kejq3Rspb2hO/Tc9NDlf2zkOdgTq325iKubU2gH
bnB07JYU3DY/C1uhUq6unbMAZELMaGRI3zLrqvOqyRqXpi1WWm4tbw6cTrxl1nU6TPDzEft4
yIVe2XwvJ5OmaPPcjlo7yzQz5McSF7pCkXoJpS3KbGAxm7a4RbJM7WU+V8nwaywqc3Azb/C/
unlOvsPHD1z5dyz6f7JfnoGmEQN7VmHKVRiN6L2xpxUmN9BA4AU9encLpcIAyxE39ui3Z5QO
0NivdGDPasx6xWoD9kXe2C1Vw7kEGEkT9iQDIDY2XKV71qiqgeEMuRvaITN9PqOxwiWe0eos
PeN5u4CVtrhoyxEwzRXACheODXvI/kxPpWKgDUlctOcIeD7jPXImHnHJYJKap/PpslzBzLCy
GAP7j6LhvDK9woWuGmqv9tiVccsDbXRGY8txNs2HvNfImFiaRbuKesej6d6WKrsE3S8yy7MC
DkQM7Fldp1fv4HnrwJ7WdQ0vHLbDdcM0Ni5oN8dP8GllV8GBkht6Vte1+CtBo90XdEvtcDoV
6SNtwp/kALw6SmOtFVatsOX5teM5+ErVLXEJgRbbj1KbeIPbCPKiHaquTM+Cl7iEQOtN1aVr
enegDZey4Vz7K1U3uHw84pIC7cVFGmsHzwLKYtTEP1xVpn19S1ziLSMkVEWqlNsXCFN1O1z/
2KZbh0UyZtXJha1wdzAY4u2q8gcb5QnaVzuwp+WcK/iqe0GPizllNDzlhT0s59rVDY1mHeCz
ck4uQTfCA3ta0HW0vW9gtxTq5svtSE/wh6EW3llaDbleGMxI9C3pCV95Hy9xyYCKGpKh9JKT
uNhqm67ZW86Dp41XS1xCnRVuvZLFRq+hPnmyxX9k7pM3qHw8olKu9GLr5CWUXQW55EU76nTT
rssfS1zo8hqyNIt02rvDzX172i7Lvz1jT8lop97SllriHQAGCNFiBfWt6H4Tn7wQaw1sMLmh
Z2Vdxiw12HcjsWeFXb0MPd58QQ/Lun51tD3yJ/isrNOLUUOJgT36+bRcBJrA39Atdbqp44WP
4AR/FmjBVaqL1upu4JxDXrRF1E2daZe4yJUTke7ETEwOi7otMxvThNvPJS4h0FQt+yCV8jwZ
VXXf7H48uHw84pICrVGrvUtrr0EdTNXtOEkuPg20WOIS+iyWOdU8texZ3EZV3RYy067Yz0Uy
8YTFXTF1jR0W6Jf6dlX5Mx3yrIB79oE9q+X4MkJHBm/sWS1nl6Nt4y/o0bsr7cpVDy0wJfbs
3bUL7iEe2NN9nOKg2/HAbtFyU6MLH4kJ/iwxQWvcWc3ynHaUzq4C3XQ0colLuXJJCjaxzBJ6
a8qW9IdSvyierHHRbiKx0sZ/mQQdPtlyTvmFQ97g8vGISzrksTSp7FIE3HznRVs66eYVujUu
ptScQgFp5wY2Sq82nz2o0K2R0V5qLUrxc8mZjXeF7qCW+yXjtzVjC8Dx2xt7+tQ1HknYdjax
p89d4Xitsite65lDHhvYhDiwp8uvrmBvx8Cefv7SJwJ9/hK7RdRNDS98RCX4s6gE5WatF8ps
dPTrvnaMOxedO9IucUl91kg5VqfUdrARyZYp3DKdwl3kEhK7dc+xAnXYIObbRd1ISnjEJfVZ
zUDjYGTCYMl9k0Ne6fOj/TUyZpYhFmIUO6FvjvT6R4VuOh+xSoZUm2iLX3/8bv5/Mv8PAAD/
/+x9y7IkOW7sFymMIAg+fuCYdZ3PkLS4i6tZXP2/CYhgaqEWozx4cXCqanK6rXoWHt3pycgI
Jwi435LZus3equ6bHfLQn97ERlfoKuyhdmGjK3RSwRrYxEbLuYamRExstJy77H0xOWfY6Bpd
R89bJtZFzi2nXetMS6jPUizMjV8f6EyqhdCv2ylttq8k0I8tLmYRZ15/qksldUb7730Mj8sy
LGqTi7BSUSWXwSFE2rSh/ZuWW8akTCIfj4ioKrN5iEY55zQqOL5uV3mQudkw7JGR0lSaip3q
1wYewDhlWOS03jHskSljkO7kskWrocZpby33WxvkFQKPvSY2ukIyGsMVEsNGV+j0oQxKugsb
u7509AFKkomNXd92VAHTxic2+li4NHBuY2JdJN16LmJmJdRnGRZiIwS9ceMxwFmC7OLIT6fL
8uKFu8NF1dmQSkMFXRZ0LoKO5mN7vG6h2+Oie7zUTwfDUuFhApc60J2qm0kJj7ioPtNfZyo8
dF9TKxguknwSc3Nb92nukTH3QkvyUxWUCFd1LmMeda3qNsnkmu0QuUjnBz10b6M8+IeMNql7
9Kf/xlZ5urcALQUvbHT5pjbQrn1io7VmRmdIJzZ0fc0Ajxh0e3uBQ79Bc0phsEA8saGfj+uB
hghXF1PWO6u8OoMc6hOL/WpDAdQtazX3BE60V5ehgNsJ3B0u5oaZWuLMqcEHW3aRi9Jcrcvn
FpesjwMhos65tw7ay+lFPkpzvZuZMQ6PuNi5dhKVmc1KuoyqZhervFRXRd0fW1zsIcM5S2KS
NgbYXu5kqsLLyZPPTTJi1j2qMzsRF3Bl/lSh+c9klVcz2OU3sdE1nCrgYMnERuu6nsE6xgkN
V3VC4IPpBQ5XdeDyXtBYTWdRgaBV3gl1qR+uazszz6E+sdqvB0muhUaiwQSOrdpFLqpubZW3
w8Vc71oVFXVMlzTBrPJ8VN2692qHiwq0osIhpVbyQKvoh0ey4a2om2kOj6iY/3FtmXvqlAhu
vHQSdesS9Q4XczIe1O2cXn826LPTS9Qt67qfm2SkWEaevhWTClRY073tj500XbhRnqAHwhMb
fSDc0ZGIiQ0XcwK2tExssJzrJoFwq7wW7qnCdsyLfcCJjRZ0+q7FPt/EuhTq1u/bmZ1Qn2Va
FJGcRHfqxKiDkvnrfXGhbocLH9SLvm+Fe80ZzIFgHyfnM0V08brd4WKFOjtnNmvqlGGvPI9N
ob7lVxPSr3vs4xEXOixpma2wRT2BP2knr7y8/L382OJirnel24RdKSSVUfdjF6+8nH52kz0l
U/SxnmodPSX93cCTuFu/mLeo+3W88prg2s6w0c1gqYAHYBMbq+3aIYwaPVzYYG039IcN9ne8
wLHarhyM1lwmNlbb6Y6mojWhC+tSrlsOS7aZoNCeJVvkkiVZ8aF21NW5utSF7hzztricjnkl
Df2fNcqhEb8+jnnrQ9gtLuch7OCkC677UrSr2esQdumYN7l8POJiMi232kfTDQQouZ2k3Y1h
3haV0zBvZKJWzdsZPIpxMszThfnJPfaUTBk1jZJEtXeu+T3CEWmyEvq6P0dsQfeSiY2Vc/no
8OzGhY2Vc3JUBj/fxIauL3drDwcLTRc2+lxdH//wubpho/s5c8EEwwV1kXLLEkqbyQntWXKC
bnLqYEqiWh0cYPUyzGvLXqctLmaTorIn5TKYG2gbRD59jo2WFZRNLqU3q52chUewpdTruHLt
rTK5fDziko6euu4WiKW0XBtaDfJxzCvLie9NMlKUQ8p28KpiGx528DgU52V34OcmGb3LdFn0
NstFN3To4evbMc9DzH2XY14Bjw8nNvr4tcEWHBc2+viVGtiLOLGxmm4chD6UJjZ2fS2LF5wP
PaHRim7kBt59F9ZF063i0f9qMzihPQtOKJZn2Un/QYXRgFOPyedbTbfDxeRZUtnAo0ruqC2J
j6TLq2X53KRSWh+jWuhsSWC6MW2eiT2QdDM24RGX0y5PSi8iY5izc6RdHq+DZzfJSE3c2cwT
mlTY0dllTPrGYmWTjFmskBiP0QQek37X5xwkXbhdXj1N5zEtZ9jo+pzegXCghWGj63MCjgtf
0GgllwWsvk5stJIjNDz9hEYrOWF0H3FhPZRcXR+CzdiE9izOQqiRmbIVKRksnOhFLkpubZW3
xcWs8oa+ljIPaSPYKi+vD1r3uIhqBRXXQ0qpYAAebYZG/U3KLSNTJpePR1xMlHFPZuKsW4aM
+6q4SLllEPCPTTJSRh2plpRH6Xh1zsctb12d2yNTBo+SB6ekAhXcMbyrc7+1W54+6kFFd2Gj
T+QKbEB7YaOrc5wynGdh2Nj1TUcrqFvehY1ukMwNDSm7sOHVYfT3MbEuqm6lhP5qMzehPcyz
GCNLa121HRzP4ZKbQKUtRyO2uJiqy01IuvUqgpVdculap9MMd/G+3eMiVq/npjqVBpiFRS5q
+84tb3L5eMRF9VmpufeqYrs2tK9Rr/IQQrx0pv6xSUZqLTmVqoIoNdAO1ckt7yZxdpcM8ag1
J9K1QQe9ftfE2TjN9n//8R//+M9//Mf/+dd/oZT+5d/+/f/9a+irCVvG6MNKUAk5PIwdNPc3
eQbqbxD2ljFsdA01oe0/ExuvuGFvGYWGrq7uQWiA3Q4TG/rtSToygY1qExv6+bgefYC+dCfU
Q23TusNxxlq0h7EWpQz9K+WUGbVSd+nXuvOW2eLCR+opUc61UqvgRs0u8lDbZbUun1tcbO6E
U+m6AWoldTQGxmdYJa3r9DPX4hGXdHAlGqpQuatQBTtI7CoPgZp+dpM9JdP0C9LNVdbNot5t
aNnRo/s652V25OcmGckjNRHdCOVSMnwc/rYM9NJz32QZONA5y4mNlnWtopWfCxst60YCJ6Un
NlbYVRND6OGzQmNlHR0FfDlf0FhR1w9uoJnbxLoUUdcdaDPaoj2MtpB0iYeece8Pj4O+W1m3
w0UVWkksRElKl4L6y3hsVqitrT+2uJhCG62ptEvcRoONoD1KdSmtxMPrHvt4xCXZzd8kJ2Ld
GTJIJvlMId84QW+SaVyqvulUnqbSwJePk2ngOhXvc5OMNZ/2rv/eweO0vfzCc/63rPtu18BO
1n+HrfLERrebmR8n2m5m2Hg9B74jT2i0mmsDLFZPbKye48Mm5FDHQMNGKzqpYNFhYl0U3boR
bUZItGexC2LzBFQHSaoDVnQeXG4cA7e4nD9x1u+5MY1KaKHOY5+iim5dqNvhouKsU+IuVTV8
q7Ci85lbWY9GzQSJR1xUm+XOkqimklsGz/j1Khfn5GW6349NMrUmVUBmnJ5VaqMiyGOvnqn/
7C57SuacDZfeLUsbzTtLm04Eb0X3i1gG9nykhhVlL2i0rOuoxdHExsq6plIXHCQ8obGyrh+Z
0WnaCxsr60R3kWDe3cSGfr6i752B+i9dWJfz1/XZ2MyQaM+CF2qSXMhyPXpG7ZCO6pFTcifr
drioQpOmL12qjeBYbr3Ix2FmXULZ4aIKbZiiU20n+gc6Jc4OXag5lZ/dYx+PuCRLBUxVRFWd
dAF3usklFjCvLZl+bJKpzQwDKRWmDO4dnNwCEy0T2za5lKFfUNUtu767Ca7TvUdY/v9VXbxb
YB3g431iY7Uc6QMPPDI8obFKTo6aGWxOurChq0uqzwT1vbmwsaur30kBv7+Jjd5JlAxuaifW
pUS3PhCb4RHtWeACVUvRyqwvJzTFRy/ycQtcj4rucakqSoV751EbeOhqF7loubXpxx4Xmyhi
MuMPlXSotYzHRJFKhrWWm9kRj7ioKutZ/6piEa/4sAd76B/m9dD7Hhkz6Tc9pxpIBLTOd3IL
vBNze2SK3mBEo7UmujBvt8BIMfdt88jgwdzERrfR6a4PfKte2OhjVxpoy/mFjVV146AEVpgm
NnZ9q76j0HnkCxv7+YolYYCf78K6qLqVm8lffcZG9GdRC6T7867Sro1eBI1Gdak23qi6TS6V
pQ+zpWs9gycLbqpu+b7d5FJGlVST3tajgj6OXqpuaZv8usc+HnGx8nRtnS1NsZeGJ4J5kKHl
wvzYJGOVxsqVdZtWwMAmJ5MZ6suI510uic3/kPUfXYXd2y8wTtTF+wWiXQITG12hKxms3U9s
eI0uobECFza8RsegF9kJDa/QJbB56ISG1+fgIcQL+7X1uT5TI/qz1AgVcUyjDKn6B5qA8dX1
uU0uZuJmCRhDOixKv7o8t0mljFEL5XL98YuU5yaXj0dczvKccG+qs4duaNAi0FeX5zbJCLdU
VPV0/UGjWU1fX57bJFMGpWyStCspsBv9XZ77re0CzbAcLc8ZNro8xx1sLDmh0cU5BscgL2h0
aa5k0Nx7YqNLc62g4XsXNro0Jwm1frmwLs1zy5mIPjMj+rPMCOr6qhUqkrIkuDTnMUdwJ+j2
uFSupWeLDZWOVp2/XtHtcbED19xHT1ISaiLvVZpbTlJPLh+PuFiRLRebpLbkvAE+sL1Kc2PZ
oblJRoRH42KhZtLAlXGqzfH42V32mIzF5lEqqTUL8/mjrQJ/9jEYVnQPXhNg+7fLQ8htUiPc
Iq+CT+sLGl24IXxCg6IHNFQ4orNMExu6tqdJMj8wVPbYxj8ZgRhHP/2tkB3OhQ39fFwPAm1y
LqiLxlxaBfcZZtEfhllY1ZBLqn2AVQMf1+M7I5UtKnwk4VJbJhkZbLayazwUZlmmxW1RyUem
lvj0LORM8NStixn10r/5dYd9POKSDhZR/VJU/esXRegZo5M93nI8Y5NMozP5LulmrzRQQDjZ
41Ff1wz3yIidFliZnXvK4Gs+bf76f3WF+U9jj9dsBUHVNLHRxZsxGly8MWy0rOsVzxkxbKys
k8POaNDDVsOGfn+SDrOgQn2PDRsr65r+N8Fpkol1EXbrvr6ZZ9Gf5VmU0WqmITblOdBsDp+c
kb50L9viko9h8XHZ/NhSQm/tY7jkjMhy8naTCymZajOe3DvoK6TSzmNdxvjZPfbxiItJO+VR
SSjpX3AvnJO0WxqqbJJpSqVWFXg9c82oTvVwpchZ1o19e2QkSz4HT0isgfTtfBws7eIt8iq4
yhMbrelqBl29JjZc0xWw1DSxsZquHsTgbnNiYzUdH5nBA9eJjdZ0TOD3N7EuHX7rw7qZmtAf
pllYNlkrZpQ1wGAYN9vj9VndDhczRkmdmx06Cgn2tnVzU1kmAm9xsXKdtSlm64kr4NbQrVy3
7iKdmQmPuJhJXirUedioEcO+ch6boMxltTA/NslU1UGtFt026N+gabxd5dLitz4Q3iNTRHdA
Q7XiaB1sB9GLtn4xb0n3q3jk0THQLPuJjW4FQ0NtL2isrmu4y9vERus6EfjbE4/W42eqrsCV
ugsbq+r6URJaqbuwX3wEO0MT+sMwC2JWSVctRRctLG/2+Tw4g93hYrkUNdXUVOAn1DzT6xCW
1oewO1yytV9Wm1mlzB21F3Jpv1QFtq7UzciER1xMn5VkgcB1lJpBuR2g6vbIqKrTLZp53rDF
e0WqOh6r2vbnJplSbWKDeymVcMebt/Wxw+BGvEleA4t0Exsr5fIh6NTBxMaKudO6DRRzFzZ0
fakfKaNFxAsbu76iChK8/yY2upszJ2yE+YJ6iLm8npCceQn9WY4FiYU+9DKaVR7QmQ2fEt1K
AP3Y5FKZ+zB3iFaqwHYqDsPbKuaWyWSbXMoZ/ZDyUFUHjqLbRS7HruuOupmW8IiLZYy1obfZ
UIVN0kKncPM6cHaTjLDuGPQ74qK/GPyk0mMKl5cpNp+bZIo5ZPbUqrTWwf3Pewr3NzbJa8fo
YEfKxEYfvBbQ1ueCRh+7ZkLDni5stKKr5yEepugMG118rfAAzIWNVnT6PAQV54V1KdAtc6P6
DEvoz0IsqLRWhEu3+ExUO/houps53D0utaTGNiapnEB3T7c53GVq1CaX0s7Wszws8xGdj96r
nPytQLeSQa977OMRF1Nnut/vhe0EBw7AYo9i490Y7h4XkaLPGnOV1A1W7Bgu9fXZ/h4Z3cmV
NKRkXaEM+n2+LfJ+T4u8hpqCTGx4fW408BziwkbX59D92wWN1XKmvkGDvBMaXpsj0M1nYsNr
cwWcEJtYlwa69Vt2RiX0hxEWwpy6WF4UFXQo4suV3B6XyjXxmYPOvaJcnJTcujq3x6UMsyFJ
Z28jmoSzWTb5n0ourY/zZ1DCIy5WnaudpPViAfVw/9xXF+f2uOimR/+2ntPBGezz2R0jeFCc
2yNTeh0pcWtieWRvi7xIJfddFnkV7J2b2Oji3OhoV/+FDS/PNdSG7sJGl+d0twwfuBo2ujzX
OpqBe2Gj77/E6IHwhXURdcsX7phJCeNhgkXl3JsdhiXGc8k8uJS2Oj7+scmlFrHDI8mlw70E
Lp1N1PKyf26TS2nVJiKIqDTQ98PnyDWn8rN77OMRF6u0ZU612t5B7zU4l+yL63ObZEQkUWNb
GeqghZFe5TG2m9NyKmKTjKrT1Fpu3FJtuInJH1mf+xKbPNjDzCW20m1cI9wor6Ee4hMbXcDR
VwtcwDFsuNbsYP7HxIaur+ofwqUSBbfOSToIjWSd2NDPx/VI6GjDxLocBC/Lh2NGOYyHUQ69
qny1MM9eMtxE5mLIvJ7U2OLCh740e0v6+s8DrB7qNR5P+Jvx2y0q5/ht4i42dcLgYKTb+O3q
TPt1i3084qKSsdh4Z2XR26x27B4zIxYPoZmWJepNMqrHZNSu4qxI7mijootbHi/Nbj43yYje
uWXURDSkwHbMb7M8Lz33HSVElWqjYT/CCxp9aqjvI9jqzbDRoq7DFZkLGy3qekULdBc2VtZZ
6xl4Kjyx0bKug+60F9SlfLh+4840h/EwzcESzVPqmQWV+E6TAXeiboeLCjTulubLklU8wB7I
PmfC6/LhDhcbv21MPbGU8ygwcvp2ObAxqXw8onJaIPMgrmJTuPjAhkvBjZc+eZtkVGYPZq7p
HKdBNZ3PkfC6eLjHRXI1ElkFHRwB+bbJ+41t8nRHApupGDb8QLjgNnmGDddzoBy5oLFqrh6C
xjFNbKya44MaWIKd2Fg1147Uwe9vYl303HJaY8zshPEw0aLlOjpZS1lLsPGxSwzu2iRvi4ve
BFIapdJ7P//dmEeej5vKSjZ8blExC+PEuoHKRglso/fxPb5zU5lcPh5xOd1UeLROeaiaAw2c
3NxU1nuGPTLV2uFqL12fiGi7j5dHnix7/DbJFOFeKykXfQDAK1O2yLwF3a9ikpePlEBhMrGx
uk7flhU83JzYWF3XbCME1ukubLSyKw3Nc72w0cquNLCOOLGxyq6rWgOn1CfWQ9ktm+P+GjM6
YTyLtBBKzHxOfI4GzvJ8uVHeFhfzvCPWH3rRfzNa4vUyylt63nxuccmH9Q5WHkksfg38mepF
HgJi2U72usc+HnExkZZbb41Um/QKH1l+tVHeJpkqmTI3aSXRYPQw2cn+eL2B2CNTainJZjgG
EYPdF2//49/UKE/ApsOJjZVz+egCzh1MbKycs6NeUI5MbOj6qoTsjE75XdjoY/WW0EHrCxvd
y0kCendMrIecy6sH+l9jpiaMZ2kWVGyfPmoZGTbp1os85NzN3MYel1qqvmJzt2PXjnLxmdvg
dQ1lj0vpmfWh1dlGHlCZ7TO3sQz1et1jH4+42DBuMZ/gctXr0K4t9tCmulP5yU32lIzwKLX3
XMpoaKuCk1VeXvYGfm6SKV26TdU0Kr3hcRbvaVwHOfdN07gJ3IJc0Oij10ZotOSFjT56JTQq
YmJjNV3XnRZ4uDmxsetbj4HmdU9stKZrAxQOE+uh6dZWeWNmJoxnWRZUOBFZhT09sMrz0XTr
w9c9LrWObta0Q67uNkzTuaTOrq3yNrkU69rK0i3bFDQE9bHKM5vin9xjH4+4mFeKybleS5Yx
4KYtF4cVvumm2yMj5hqaM/UkHXVYcpvFXe8c9sjYkasMtuNk1aeopvszZ3H/dK886WBn/8RG
l+gG3GVyYaNLdAIneF7Y8BJdAp9GExtfokNP1C9seIkOnAa/oC7nreuzsJmZMB5mWRRqLZVq
kaBgMkdAgW6PSy2dh/6OVJmirRheBbq1W94mF6XSqqpT6qOAQfUBBbqZmPCIy1mgsz2DSVM7
Eo8t0P3sJntKRkoiaaWmImj6XUB9bo9L6TVTqpL0l9PGuz4XqeW+qT5HTUBJd2GjX/kFtGy9
oNH1udxRw64LG12fG2hz/8SGt0ii6YcTGy3oxoP63HCqz9X163ZGJoyHURa1cs+pFYaPuMml
VUsl3ara8GOTSzXfv5Qzpw4nrVWPo/C78tweldKstanXNlqDj4+dkizWJeAZmPCIi5ne6baB
TxfDMuD0BxervLvy3B4Z1XFpdC66bxAqcEXrq63y9sgUG4vqJZehKhXXp39keS5/hVUeGkYe
XGxCZYnDo9FB/n6TfZ+gTioTG13PTAmVHxc2Wv4ybMV8YUPXl8mmfsBf54UN/f5EX4AEGuRN
bOjn43ZcHd3YbLBhXSqaq6LGX2PmTIxnORNd34CcuAxVwAOtaA6HIdTbCZIdLmbGl8jmULs+
jcCjdi8Hv7TWvztc8pGbVc3I4lnQWpNe5FLRlPWU0oyZeMRFVZYxMX9lXSC0r3V3BPVvknFd
0dwj0zK3YoGBqhgbaE3h5OC3TjP53CQjrBo+i3l3dtBSaLc8+6vL338aB7+W8Gb5iY1Wdq2A
wy4TG63s+kDLKxc2VtnxkSs4GzyxscqOdM0Y9vAzbKyy68eo4Oz3xLoou6XFGqWZNmH/54m2
G7WzpCuuCmz90It8fF+W2m6TDZsHNulLqsjoA2z1t4s81F1ZHiVussmHjTrTaPp0GBk282OH
yW3Vd8uuiBebj2dsklVrKVOTQZUEDJVMTuXaupwR3qbTuJlLc6UqPMBHqV7lcWxNtJxF36Yj
IkVa4t6kJtDafLdk+5Z5v4CnX83gsOvEhneCod4qExuu7x7Iu3h1pw9bWN0ZNlbdlYMS+Pkm
NlbdjSN1NHjjwrqou+WxNSV6KYhn0RtDxZ2chikJ3bvbRS7qbjlYsslGtyFJVNXVTtVc5EB1
lz2cbE5pvHrjbrExoWZeKbWrtsug63T2sUxJeRn09mLz8YyN6jQVHN2qXbpEAhaJ7SqXkteN
utukoxu2Tp1TEYsUROWQR59E5mUX7+f+6rTeRmKzay4EB/HtNb++1d0vZPCH5kdNbLTIQ0Mh
L2isxGtHRe0RJzZW5NUjMahBJzZW5IllB4P2fhc29PMVOrKANaKJdRF5S1ddSvklJJ5FPqRS
B49qDn8FfFVlH1O8W5G3xcYcvJte0oplzqMa/PAYpNKlWbaOba8NF5YyVBZVEjRI8vAYbFKR
99M77eMZGxUEPKi02nRL0QTWeC4lr7pMWdtmYxsJIt0gZeYKFyQ9epgyL1uUP7fpiP5qVKvm
LKm0Bket/ZF9in+8098A36wTG6vr9G3Z0THiCxur7OSoXMCzrgsbur45HWmgwvjCxq6vfifw
57uw0fsKyWBA+8S6KLulYwclfqmHZ6Ec2Vww9Z3be0FjqPUil+TcZRPhj202tXAVTqT6jgUt
Rno4ClFbaqHPbTb6llX9oC9yVd3o0uy9bP8m7G7qxPzSDg8DIDJxS70zjZHAoXW7ykMKrQ3/
tukI99YLnVqI8NRZn5HipT3M/uoMzo272fbo4qB03kPFHsru20z/wBfsxEZ336UGTu1MbPTp
LI0OJ+gaNlbgkW7x0bHdCxu7vlVfu9hj5oLGfrpygCM9CnQRdjenZeUlHp5lcjA1fZpnK9pV
sD+cXM7+qCyTgH9ss6nFDHYH1STgfGSErtskI0k3fMlMPEoCzdh84lLyOWp1f6N9PGNjxbdS
2Nx7mIhwv2CXkt24KQ5v0rEmtaG6TnLvjeEuNY8pEd2G/exee04nNavcq6rrlFHVvXevvXXd
9xr/NcZ+fBc0ul5XKjjmObHR9TpB650TG12vyw1tVryw4fW6Bp50Tmx0va50NMD5wnrIuqWP
mb5t5aUdnmVAcErUzf64ow3udo1LuW45wrhNppZaW0ujlVHA/nYv7787WbfJRmWdzTCOWjIa
Zu4l6/LN1I68hMPDGIhs1tScCldmXNZ9eb1uk45w092D9E5U4PhZl3JdopvGzt3FGdnsP1lF
KhWwheFdrvu9PQAzVi65oNHFupJA0+mJjS7WsaBP5AsbXazrCR01vrDRxboOq88LG12uawn0
eJxYl6LdqsylL936khDP0iCYLeQ0l5rg6RC76KtPYzfZqBAalgRrgVJg7SGiarfJRtIYuXHr
oooIHWN2qtrdyLv6UhAPEyGE9RY7uYzW4dBWFzMUuakPb9IR6UJ5kLAMgk2RXewAqd8MU+zS
IdXc1pNhx+Xg5M6fWrbjrzAEBO1/XB5GbiMe8dZ7tYHf04WNrukQoQ3PFzZadWb4sOrChq4v
p0OfMNj3N7Gh318ZqiTBRIiJDf18rGuWwfWdWJea4k3PfXspm2exFV3MdG/UoZoA9GXQizw0
9K1ByxYb81pRKTDsLDKD9j56jUs4XF66722SyXrX9FaonnM3BfVnyQ4bAhWdNz2A7SVrHkZX
MA9JrLImWeEXFZ0edHj5u/mxTcfi1JolpNCQCntQu3jw8bLH4nObjmT96ejCcC0Fjam3q/5E
0fnPZMOX0E72iY2u7QxQhF7QaI3XUWeFiY3WeL2AJosTG/r9id5R4FbsgsYqvHZk0Dv7gnro
u3JT6+kvEfEsxKJzrn1IV4nHYEeTXeRSVbw5ydtiY5mQZdhEpcXMgiFr2cdOsNFNVXGTTSbO
UlOy4G30OediOKMC72Yn0V8S4mGQharUXEfm0pnBEwOvXsDlVMSPbTqNyshWu84sVdCpiOax
OpxvegE36QjrJp7FjMl7huW3bD0I3gLvVzDg6+AIwMRGK7uK2i9MbLi2g0ciL2ystss2loOp
kxMaq+z4yAI6qE1stLYrFfW2ubAuZ8bLUC9K46UgnkVnjERm/tFy6gV0PHSLzrhpv99iwwdV
vaIKK5XWMHVnF7mou5uxyi02Vr4rJHaUPyiDytsu8lB35WakaLz0w7OYBh6ZOkkX/UPAfguv
ALlyU77bpKOKzqyIi7SSCGxeTi7tpznRjbrbpKPvn1oTdxm6NmCvvV71tlf2UnffZcCXwED7
iY1uHeMOHsNMbKzIa4dk8Lc/sdEiT3eCoEy5sNEyTwr4sJnYWJnXbcgAPOS+sB4yb9kS9BfR
K6mBnqVo9MI9j17LINRY6HDJOr47o90jw0fSG0GUiNSGn9G6zH3Q2hVtj4zqNSveDSkt9wTm
vdlFLiJvvZ2gV0rDIzZXSnAZQqk3HuBEYYDI26VT7ZHNVEe3mBP0UNNF5J1DQPf32mM6pVHu
2QbAcj03k5jI29r7v0Xe9zrwtUSwA59hY4VdNjEEz3wYNlbYmaseKIwnNnR9aRwNdSg7obGr
azPOYHVsYqN7P7Pg87yGdem9W0980CuigZ7FZ+TKQrmxiEWsov57Lr13NxMfu2wqq56rJNYQ
BbqIeU180Kre9bnNpvTWdWmKlYfQJo/NIcu/nc2unR7pFdDwiI0FYZQ0mHuXNArodeAUn3E3
0LtLR+xGa6laPlqG55NdJnq5rivF26vTW026xyupcu6o7cx7otdD2H2XAV8F9dPERp/Olsbg
G/bCRp/OEvj1XdDQ1c26I0ZzUSY2uixbUd+AiY3Wd4NAR5CJddF36zMzeqUz0BPLfAv1aNKo
lsRUwQl+N323NmzZZVOLFGplJLKh3ljDllWp63ObTWm1ttEL9dEy6hbt4fx0a9hCr3CGR2zM
eoXPgJbemBJeGvI4bL7z4dulI1KyCJHYHVdhg2Wfwt26z3N7dYbN8eRchq4T2Njwjs74PY34
egZfrRMbXbirGTXLuLDRhTsZoJnMxEYX7jqjn+/ChpfuChpNcWGjpR2h0aoT6yLtbk7KXvEM
9DA6o9Go0iwctIJH9HbRV5fuNtlU7pWVEFFisDc8onS3yab0OqwfMpuDxi9TuXuFMzwic1bu
arVZUxJwC+EWe3tz9L9JRrjQMK+WMkYBOxl2hxD+RmftxLe9Nr00ZpJRWTq+Ou/YWwdd9011
uwx2WV/Q6KrdaOi53YWNrtrp5hQu2xk2um7XOvr9Xdjoul1PqOfNhY2+/wjtWpjYrxZ3r4wG
epbRkFsREmYeFXRmjNB2m2RqYX3bUrX2XzS0xsuI76Zst8mmtNaIzSqxonkTXmW75YjIf99o
H8/YmLtJ6l313VAJkQku23noIZX6P7vVHtMRkZqHKtVKmcEKvpMRny7Pz+6156szhugOdEjq
esPBRnx/ZNnuS4z4CH26enje/sZWfBVNG5vY6JoOnO5xQqNFZ4Yrihc2VnSaeSJ61H5hQ78/
c14p4M90YkM/H9dDn86wEZ9hPURnWb1tVAu8EiToWYJEJ5VnNj1iji2wUYtDped+yGOLjZnq
0ZDGjakUwYSNlxPfjVHLHhvzXBFLwaxUK/yscxrlvTssfgVIPGJzpntYQbEx116j0z1upjw2
6TQLO8zNSsk5gRNFTk581G+Kipt0hCwVJ6dhNtADPvt+O/F5qbtvcuIjVA1PbPTBYj1PN7CD
RcNGyzx9bcIyz7Ch68vW5wdafE1srMwjvafAzzex/+vn+y8AAAD//+xdS7LcOJI8UdOA+AIX
kFm/d4qxXs1iuhYz97eJSJLayEg5URD06SyzLvXCWUpPZiYd8XH/gTKvdTC66cDOkHntRuad
SRL1WZJEK1JJhYwMT5JocxxbbmTeEJtQbCEhWrWcwRRFHVumzGt6vWLzOciGttpDtHI8gM0I
LbTHRVM6x9eGy/XMkXjE5mW4XHM+QVysgEMhk4qLxW7q2IN0PM7mcaCgGiJPQWfOuGqKf7Td
FBcH6Wj8AlDPuWAtFY8afvvxTZJ5y/34egGtRg7s6t5d62gK2Y5dru8amhK6Y9fqO95QO75E
rtV2nEazYAlvx67Vdh7PUPD5dGCnaLurR1Q8cc/AhvosS6O7NWmt9RYCHt0pmLKdfOfGN8aG
t6okJeMnmjqYCJAXTdF2N0YtQ2zSc4WVvXEJNmDNa5ZRC91MBZ5xDY/YhEorLiUZaRy169K5
QJabY8QgHZP4UktP70dyQwPp5rjxXebrfY7fHZW4xGshtYrv8w7ReWu7X8WNr2bZAZZ4iV0r
8Xwr4ENph64VeL6pPPDik/VefAUO09ixq0VeHPSx13dg14q8nIdFC3g7dorIu+menaEN9WGg
BoUc4las1SLoesGcQI27At4QmzTWq1SlCWmqiaVufJe+IJ+DbGir3snFpXLa8qEFvCnTgTeW
y/WMbHjEJn31KkkPveXUwbCTaWZ8N8eJQTah7TKbL7478eSDJeskM77vftQe04m7kunWvVCt
4E7A24vv9/Tiy20ydKU3sWtlHW2tggZVB3atsNPNCIz5OrBL72/tm1IFX9+OXd15j6M+6Iay
Y1ePf1YDhd2BnSHs7txazryG+ixLI561Ie1ywivkA7z2MUMK3bq1DLIxcQqVWlIOoV6Tk9xa
+KaiMshGWpwIyJ2IK+gHMs2t5aZ6d6Y1PGKT1bueCwVpbVIdHO2e5sb33Y/aYzrK3V9GlrW+
ZPA6M77bpd7Rm5OJ2PW12lsa+DvwNuP7rc34agHtZA/s6taso6/vwK5uzdYGthcP7NL7SyX+
TrDh84Iur8pW9O7u2NXyrlWC5V1ip9Ttrseh6ExqoGcZGhRCqGVqQtcKrlpOk3fX1ZRRNrkz
qk3Sf8LQudfN5uxXXCcbjLIRr7leUby6wtJ7rJjyTfvv+iBBZ07DIzYp1LqJ5AZs6wLenGn7
FVdfnI9hOmlwFNLbTay+UjpWbvVeHyWG706Xrl3EOr/qgm95t0reLfficzSd6sCuLtx1wb34
Eru6cKdoetuBXV24g22MD+zywh2hhbEdu7xwBxcWd+wUZXcdPE9nVAM9jdEo6ZHGtViBoxom
2SzfPG4H2ZgW7ynutBbYmHhO4e7Gi2+UjTTpVIpkRQU85kwr3F0PeNIZ1PCITSq7/Bpk8ESc
IeCm349O0Rhlo9xa0TwPqaNGRwsKd8M3J510Qndbz39g2f1245ug7H6WGx85nKKR2NUCQF6F
DEwAJHZ14Y4LaDTxgq4u28VDEPRa2LHLC3cKjsUf2NVl44K6LR7YGfLOr7tldCY10MMUjaah
IJo2Y4I3ZmlCGTfk3VX54WOYjWkXb9Zca6+w1fIMsXpbuBtkI3FsMbPuzATOdE0r3N2UiM+c
hkdscvdVtPTerGSmLzy3P2XF9K5wN0hHrRZpytZJCbYn/uF2fMN3p3tT7a1aM2voksifacdH
v70d3yOhAoqUCT+SE9TwzzIJFNCy4MCuLnYWAf1FDuxyLVxB7+IDu7bYWWRzBx3zT/DSd1DT
AhnUmwd26euTssWDAzwt7tgZevgy1T5UyhlvQU9SByyzvtI0omsj8P22Kc3F2yXjMTJZVubK
aiKVBazZ5EVTxhSvl4zH2NAmRrk0belzhw5NxEUz5DDfHLzOeItHbGpIJ+Fm0iqXDgc6j+mt
b/xjbg5eQ2zSCcaqGnsPRSwNHVOc8RwiujxHfg7TUTdPRUzi6FpnXPQuds6Sdz/JJbCg8W0H
drXKcwcrsgd2tcpr4CjgDl2s8XxjQzvuB3itxuNNvMFOMoldq/FkyzgFTOPt2B+t8c6YC3oS
PRAHDPUSikhK/AHW6OOiKS3tO5E3xCaXfkJFeElTPdSsJC6aMqyoN33GITa0WXZLmYvmKDho
qDClghty/zrrhs6Qi0dsQq8xp0d3Cz3c4HGDKYlsha9NAsfYhFwLgaetdMmJENjaeoYXAnG7
TrsZpWNSS+2dmlAt4EJ7GQzveau8X8Ak0AXscB3Y5RNjiq4a79jV8q4TbgKd2LUCr5atwyY3
B3itwLN4VnescHFgVwu8OO2i+s6n5EnUS7+zeOieeRL0xOPfNlUTfZ3cawPfbpvSmKvi1wEM
Y2x449rp5c4b/3TUBHrGb1dolmsT6DE2lM/cXqV6/NvQNMMpeXkhiK4a9F8/aV+esal5kKAu
qtn9BysHdcpBgqpdbxqPsQll0zy0atwWD1qOyjub4tB9uaP/OUxHxTqV+KX3ph3sjmXK3lve
TZJ3P8UnkLaioEo5sKtVXnwaYZWX2LUqzzeDJxV27GKVx5urgTL0AK9VeX0jtIr3gq59demP
AQfOyQy7pXuNd4ZJ0BODf9tEmxNnbGxp4K6ATekFVrkcwvwYZBNyzeKp24jMRcDt6TlG56Hx
brZShtjQ1oxK6SLZQwOHKvKiKRrvSkZ8/aR9ecYm5Fozbq26U9wgdKR0ik9gLd/9pD1kkzkf
9JoHMK5FO9rZnBLnRnfV4kE6VoVzIsCLCcE5Hza0M/TWeD/XKFDBdsAOXavq4htf0QC3HbtW
1f3iNoHctnz8of7FiV17f21DM5526NpXJ1st4K72gZ2h6tqNqjtjJOhZjITEneU4rscDtxEa
IzHmHvHERWaITe6VtOKiEofMii+jzFF1N8sog2xUSKjV3oQZHZWds8563cr8+kn78oxN2VrG
oMRNz9IQg6vTcdWU0OEbP8pROireSrEcAAi5CrvIzLB/Zr0p3Y3SKelnXaRzYQb75pnt+5Z1
f1/W/aRl47jR4GjRjl09elcUPcru2NW92fhZAfXdjl2r7/qWO4yYvtuxa++vb/EzA46U79i1
ry80ueJuN4mdUre76ZidGRL0LENCtKpYCynRC1i3o8Hspm8U3hWbj0E2IdaahoBQUeMODhDV
KQ2zUHg381CDbDQ0t7B2NkND3Org0Ps3Cu/GJ/CMkHjEJrWa167dqJEV2CdwRuGA6M64aJCO
WmvcuZK0SnCIm85YBqfLOuTnOB2WWtkok2TQ6PZ3QO/vaRTYDIzOOrDLS3cdNQrcsatLd+rg
+3dg195f3oTBhvaBXXt/47iAKvcXdHVhsRbUh2fHThF2N5PuZ4YEPTH2p81bKCFu3rh1QQe7
fErp7tLO+mOQTd1aKWmpxzXNAuEYugnLmdVvElNH2Zhrq3Eo8Foc7QKEtp0i7G58ZM4IiUds
ytbj9BofMe6dWWCnkj7DJ5Duev+DdOIEkcchrsFIOuwjM2fq7qYjO0pHNGTda1M7LoXpvKfu
Jgi7n1S64wI6tR3Y1aU7QY3aXtDVhTtmvHCX2LV3t2/xGATV3Y5d+v5xRj2DAZEHdu3rK1sF
p2x26Ax1d9mQ+WflM0KCn9j681aoE8XvueZaD/h2b2VKLG+77paNsalbVyImzh1gRbN14qIp
6u7aFmWUTYu3qJfWOFQRw1p1Ruuv8PVuNp8BEg/ZFBIxftnvvGIIITYzfrWJ5focMcambGYl
Pmk900rcwC9OmbPOzHQ9AzBMh7TErwB7s05wGJ39kVU7/hEmgeDpbMZ41m9sxpezuKgZX2LX
Ck7eKpgnvkOXd4odFEwHdundrYU3qqCT3Ale+g5q2Qq6TnZg10pO3wo4SrFDpxQUb4TAmW3B
TwIH4qwjxBZ6MyvGGJ28ZobitOsizxiZkMKevVUXrfAoYFw0Y/nGy40MGGJD8augTqHOGlsF
HWfiojn1xOuhUz6TLR6xScPszum0Td4dbuJPCVHhS/38McimbLmJXFx7aPPC4L74pAUPtuty
4igdfcUEqzmxgseBd5v49zfiqwbO5B7YtQpPtngkweEPiV2t8RqD2ygHdrHGk3gagKfhE7xa
42kDzxgHdq3Ga5sbWNU+sFMKi1exA/HwPSMu+EnsgG21S9Xeu1AHmwh5zY9WeUNkQrCVEHgS
itUIlKx5zQyRV69n8MfI0MYl253Zw1NBE77joh8t8s54i0dsUq/lqmjIVWPQCLtOWSy6XeId
I5NqrbSca4zrHDWUmqTxar3ReIN0VIndUw3X4hUebXy3jCeJvOU+fEqg9dOBXa3urKLLnjt2
ubozOLTlhV2s7trWO9i52bFrtR1vjk5BHdjV2q518PUd2CkVvJtn7pnXwA+jNEyoiobSMrRp
PMuj5cZmeYwNb7X1fOSq9lB5aAt8ilR9JdNcPXOH2KRQsxY6i6QVgTetecYM3Z0PH59xDY/Y
1JyLKdSaxVG2gseIOqVYfN80HmJTMsTQ9LU8Hl9ukM6kpjGVazugUTriXikddEr8Hzj2752l
MUvd/SwbPrAJtUPXSryMbELdR3fsWonnIXvR+tiOXSvxas6qgVEQJ3ityJNNCpiVcmCXvj6p
W7wv4NTsjp1SwLs20uAzr4GfZWnEL7u3UHqVnRk7u9uk/GC76Z4NseFcsCml5QQaVzCiNi6a
IIuq081k4BCb0Gtp5qvpQCOvfWFM5M2ZDLwReWdcwyM2qdeYxJo5UQdr35NEHunNcWKITcq1
zHQm59K7wbJoisir/Xp3fJSOllq5ZrWzecfXPv7I+OA/3YgvfkswbXJg12q7dBEDB9wO7Fpt
p1v8KONWfIFden+54a/vwK69v/GeMNp837Grxz/jrwTPFjt2irK72hqN5+0Z1cDPohrEyShn
/NNcDLXxlRn2dXK5l/gxyKZm8ETGPXE2ANGkhimVVb/rmA2SkZ5Zb5nj3Qg9hk3Kjr3x4uMz
qOERm7K10rrU1gr16uC2dTr4TZnAuxpp+Bimo+yl5DiDeXUwXrDMcUrkdjPsOUgn1+Bb7Wyl
i4OWTWWwd/5Wdr+AF5/nxBps2JLY1f1Z8CfvhVzdm60NPZvu2LXiLgMnQDeUA7u6MKu9wnYo
iV392SNwYXSHTpF21xYafCY08LOEBiHv8eHz9M0Haw9x0ZR13jtpN8QmZdory1ea5lbiWm13
JR8+h9lIb6WwM3V1RRdgf7y2OwMaHrFJldZ6L6EbOIfWUPUwxWe59puq3SCdOAux9RKsahew
3D3JZ/nab/1znE7RrD+KtEyggaXq22f572u79S58BB7iD+zqqp0RaBB8YFdX7RSsau/Q1bLO
DZMlO3S1qKuKev3u2NUVu+YFfH07doasa9eWt3xGNPCz+AzV4uk30cgMdAKhKQ+nGtrr+lk7
xCZd65zTEq14eqMtdK2rLtcefKNslGuounhAt4IOxw7uMX6j6r77QfvyjEy6JGfUce+5EmTg
rOokb+W79IxROirxWfOWC+fFYUfBKaqOys0JYpCOhOJu8QMQ0k6N3r3YlaruJ1nwEbjuuUNX
10w6g6NOB3Z1zY7hxNsdu/bu1q0XsKxxYNfeX49fQrQhu2NXN4wzVgxtGCd2StXuZp/izGfg
Z9kZas0yJLZ6I3ABiKYkANxmZ4yxSaXWM+utv/QdOs41Jzvjcmb/c5hNfKrFjJpUEVzfzcm8
vdF3ZzrDIzah1Kxx9v3ZzRTeQGhTwib85iQxSCeNr6W+dswLGjM5KzvjzvBxlA61OD1Wa8Ja
8H3ZP9IU5Ye48MFyYMrszrRNj/U+fBV0aTmwq8s65g0exErsat1JjrarduzS+1sLbZ3ASc8T
vPQd1FwsAaNbDuzS18e2aUPrsjt2SmHxZvT+DJDgJ6b+cegh5e5W1K2CZfA0K5+hPO9sWobY
pK+eSCnaSkUz/2Z58cnNduUQGdookzDyzlRygb345ux43BxxzvSIR2zSi8+y8c1G1GEv6yle
fLc+LUNsyuuZ10vN/7GDcyOTfFro8vz5OUxHKW5Pj8MgaxMwbzyv+hN153+UGR9aXTywq8s7
2kGVcmBXy7yGhmm+oItFXjqcgM3PE7xW5NWNHXsS7NC1Es83R40CD+yU4uJ1yUfOFAl5Yu1v
W41f9ZKblQJH2eZFP1jijbEJuaZWrXAvZA4WF+OiGdYzdxpvjE1qPHen4BJKAnRVWKDx5AyR
eMTm5bfs3kN8VBGwbzDLb/ky0PpjkE2otTgbqZeaUq/DI3Q+oxV+vbzyOUxHM8LRVULnKdg0
Gd1deUu8X8GKD83mPbCrW8cZa4S2jhO7XNsp6AV2YBeru5bj5LAVnywu0SpvCru07NjV6i4n
aVB1l9gZ6u4mTEPOxAZ5FqaRU+vxs67UMxUAteKbk6ZxPYU/xoa37OBmpzUeUQVMYuE5WvVW
3Q2xSXUXotszIKQYGHEwS93pdalYzsCGR2zSiq+E8tYiyQZdTZ5RKqbiV1ObH4Ns0opPe9Me
X5zi+C7vFJeWUq87x6N0xMRzRrg3KQb+8JbBJcq3vPuFvPgInHo4sKsHyOK4Dh5rd+xaledb
OmjBbnwyo0L2SOX1LGuCKu+FXavyJO4ZGqaxY9eqvB7CFxxyOrBTanjXy5ZyRjbIszCN7AW6
Vk93EHDL26Yoifsa3hCbbLlWq05dOhewAbGgTzvGJgVbbbWZNuMu4FTKrBrejco7IxsesUnB
ZlRTgHc8vnyS4XK9OU8MsXkZLpcSCi9Uq3df68XXblTeIB1pVdOPz3rt6IP17bj8O3rxta2i
I3gHdq2yoy29VNGt3sSuVXYvfziwPrZjl97f9NdDJ/AO7Oreu6P9qBd09QAouvK+Q6eoumsf
PjmjGuRZVIN4yQftyyHNUBffST5817uWY2zSdyUkUC2izg2cIYqLZmhUv1QOn8NspOUWi5rk
Lgu69jElV+zOrEXOpIZHbNKIj9xVnYyZC7pY0GZ4z9DN+N0oHeU4D9UUQ521wXuwU1qzdFXD
/xymE2QaS+nOvSnYtXvLut/YiC8Um4Hq5MCu7s56AZf/D+zq7mwIXjgoLbFr1V3fcqYHNuML
7Oq6bEW9+F7Q1equN1R87tgp+u7KOj+eumdKgzxLaRAqlSgeuqYKpzTMMGYMfXdTSxlik64t
7JSyqBUFg8Xyohn6jq5jDUbZSLDIpdFm7DCbKbNqt/ruDGl4xCbN+DjkqqpZj7MEWueaZLR8
Vef6GKajRi09gkS7GuxMPGXp+s62ZZSOdO/USvCJjzI4Mv62bfk9zfhyDx0140vs6rJdfKFA
YbdjV5fttKExjzt2ubADq547dO3dta0YOLR4YFcLO1Q47NAZss6uCl3xsD0zGuRZfIZWzxIX
19pQ96PBXbknqm6ITAo0ivOldRGzuljV3VRSBtloCSLduucYFLqBMOZ6+42qu6kPnwENj9ik
WTIZxY9cb+TesCLkJIvlOzO+UToqxhpnh9Cp1RyWQXPM+K59H0fpSOfaNF10akV7Ye/4jN/a
jI/R0coDu7pnFx9D8IG0Y1dX7ZjA/LYDu/b+5rgImty6Y1dX7UjBquKBXV41hut2O3aGwLs0
z4/n7hnUIA9DNNLawcR6nNgJDtGYknx7p/CG2IRYC3HH3fKd6oyxmabwbvqyg2xy2K6zkVBI
CNiOb4okurHjkzOm4RGb0GpSxKhyZasuqCSaEcxILFdF1Y9hOmosSqVXLaWA35xJdTu+3BH5
HKdTSYrWUrq74u6Cv2WIxjr99j9//fuv//vr3//9r3/EO1vKP/7rf/+19DmFPeFXayNQFk34
VZ4gwH+GK6H0rSmYM3RgV1e30EGhHbpafIvg+XWJXXp3tW4OvrwduvTd4xxyQB3lduzS19dl
Q5O7d+gU4X3TMD+jNORJvgFvVaRlfSgfu+BAZF40Q3hfHiM+BtnQVmu2l51ac9RbMS+aIbz1
prQ6xEY3l2rqJrlfqti9yYtmCO+70YwzSeMRm7oVtu7mtRVTcAUpLprBhi5XkD4G2ZTNeloi
1UbdDJQSJX6lptSJr3OJR+9N60zxYQtKqKV3XvM7iu5fq6z6E70INccdwJt9YFfXVltFk8R2
7Fp551s8a8DG+Y5de39pI9TL8cCuvb9tS9sR7P7u2LVn1hafeXDi9cBOmYm8aZ6fcRryJOIg
rfhKiLwMf6topO8k/767qJMxNhl14h5KojtzBUXRrKiTGxvgMTa6Ve/M3JisKbj7GxdNmYm8
k3hnmMbDe1NYtZkGl/ivoymDcyTeTdLJGJs96SS3fimzTjpcWp2RdFLv3AgHb44r6WuLuRQF
rZHyorfImyPy1u5DeBw2GriufmBXqzsjfN01sauLdy6oGcOOXavufGutgj4wO3Zt+c42cVDd
HdjV5bvewfLigZ2h7vqNujszK+RZAIekO7MxF8rkClDdzRiTjefPTVlliA2FHvL0ztYq8exF
3ZlnfLZD3d10zofY6GvSkxoFFTH0yzplDuB+4+WMrHjEJndXPOcaSmeXDi5XTZqNrO1mNnKQ
jlal+Na0LEs6OLk6msABuwh9DtJJQ6DarVlQaWixeNRF6C3vfhE3Qo87WMDljQO7VuVZppuD
P+M7dnUNTwScz3pB12q8tlkFp5wP7FqNR5ui05sHdq3G462g6ZMHdorGuzq6/7PqmVmhzxI4
WHs3tWIhIBvapJ0y6ymXAXgfg2zq1kx7ziFRHDrBkIc6JQ83NN71c3eMjW7MoVklg7yogGx0
kkfzzf6LnpEVj9ikWqu9C1Fu8wjDrjVTRFG9+uJ8DNOJw5G0EHkhpgg8zY9aNH9TXv3uR+0h
m3x+CzcxZXWC7Z74vdP8tyXeaivCzN7C7u8OXSvqaHMFB8cO7FpRp5t3sPR0YJfeXS6bCdg4
PrBr7288bCvqqrtjl74+Iby0fWBnyDq6XnrRM6xCn8U7dClNuTUSuFk2ZY5QLucIP4a5cHwO
WCU+rSGE4PLDnMLdtVXNGJv40JQeRERI+eVOApUhZ8QlUrnZntczqeIRm7K5FOemnYTKa0EI
G1ab0pfVa6uaUTpKnnFt8cVWoQ4X7qZI7u9/1h7Syaa5lE4hudkbbAdQhti8Vd0v4ERIW5x9
waWKHbu6Mwt3Xl7Q1X1ZVjQ/ZMeuFXd1o8ZgSOqOXfv+9Q1c6Hkh1wq7+FkDi9k7dEq17rpP
pmc6hT7Lc+g1FFBzTZsXcGwoL5oh7C77yx/DbKjmRnb3SlwKWnSgKSsVl1Loc5BNGglRqFTJ
R20FpQNNcquxm7rwGU7xiE1KtDRlLhkS1xV2uZsi7OpdYXiQjoSucxNlVdeGDtzNcGeneuNB
OEqneyvcsmgX3x7wFBFXvT2m/76yW+xBmB4J4ATBgV1dsWvgU3+HLq/XwXuyO3Z1vS5OsXC9
LrGr63XewUWeA7u6XtfQdsWBnSLsbppjZ0CFPguoiHeuslr8rDs59nueF00Rdje9sUE23EQ6
U2nx2FV0HnxOxe5SCn0OsqHNs+PWijRhA11d8qIpwu7mCHHGUzxiExKNmkuuURhZB3+646oZ
JS663HL5GKajGcvcOP4VZ4iKFiDnjNrdVeyG6GTxLZO4iUUcnXF+V+x+YxdC2uK8CFfsEru6
YicdbCge2NU1O0WtPA7s6podms2xQ1dX7LyDuYQHdq28K1tTcK30wE6Rd1d9pXjonvkU+iyf
ojWtLTNynTvYJRt1QfhG3l1JiI9hNrX3OCqZ5r6foGxogkFF9UtB9DnIJiP4NG5KxhdzNdgf
csqerN0cJM50ikdsUqjlwKC23ApR2JZ5iryr7eYkMUgnxVAVod47GWM/VSvqdoN0unHvtWTq
ThEwuiGv+hP1HcP67sEjA3xPZyRh/M7We2AbcYeuVZyyFQJHsA7s8i6xo82qHbv27nLoIOxn
f4cuffcsNDhonrZDl7665lspoOf6gZ2iN6/8JUIFnMkZ+izUxDw7xTW+HV5Bo5m4aAYbuSyO
fgyyiS+5edDooTd7Y+zTExdN2eq4VGifg2x04yqNQjeXJgKuOOVFM/Tmjee1nrkZj9jEoauV
yk4WH+MQ56iimVEmuFl1/RikUzdmy653tr3RkMfRVdcHviyjbFwsnbutGcPzFW9blmmy7id5
7wnopL9D16o72zq+tNtX7+zGXwnmj+/QtXeW0usX3NndsWurdekeBhY7D+zau1t40wYm6p3g
GfruxndPz9wMfZJlwFuJl9bYPQSRgLNmcdGceuLN1P0QmxCeViz0qpXOBH7/8qIp+u6Kzecg
G9tSPnj6EMeN75iEyIt+aEPy6yftyzM22Vt09RZqtRT0yz3Jd6/cRBGPsQndmRX40I2hikgd
Tlae8MWhV235/qP2kA5tRUM1es8PHINthbzoLfDmCLz1vnuou/mBXd0r7uhPxIFdre5aAR+W
B3atvvO4Z+DrO7BL3z/3jQs4q3BgF+u7slUCK9sneEr97kbfnfEM+iw6Q9jiedFLryKghoiL
pizwXlYjPwbZyKa9V6+tUTFRcAtnszn94puH7hAbfeWoK0ltIVlBhycdbOE9cN7TM57hEZt0
3jOuvXHrXQvoDDHLlaXdlIqH6ITy7FmKdC3NCR38nnIwiptzU78bZCNxhFBLfdc6aM4UFw3d
m7e++3WM9wh9ih3YtTLPN+oNlHk7dq0MSDc9cMv4wK6VeW3TBv7QHtjVZTxHZfKBXSzzeibG
gDf4AE+ReTdLlmdEgz6Lz2B1ZUr3wtYFLePNMd/rN6P4Q2xos9qlN5FKpLCzyYx9tZB51/EZ
Y2xso7g1JuKNDN1wi4vm9DVvxgLPhIZHbFKwkfaqNUNwCd5/nSLzXi6t9x+1x3RM0hkxbR5D
54EPo7xqxt2hm62PITp1U3ZRa90yjQ+OwX4bLP/9rY/l7nui6Al4x67VdvlIQkt4O3bts183
62h0xo5den/TaLqi+7I7dun7x5yef5h0OrBrX1/fWgNtlQ/sFGV34793xjPoM8t8L62YceHu
DA481ikub/U1/XH1uB1iQ1v677n36mxU4ezbGeVIt+vojFE2KsUpPttxaxy0VabBp+03Cx83
q0VnOMMjNilqzHMVh3N/HLRHjKsm+M3f1CM/hum0Ws3jCFE4VDccnTFjFOd+4WOQTjcqqj1E
arACFyn/1IWP/xALPmJwSOvArh7AK4Z68O3Y1U1auMl4YJfe3zTWK2gwxY5dXZ0tsALdsWur
i7aB+7wBnKLtrltmdsYy2DOv/J5DNyGIenrXoaf1OSZ8ft0xG2VjasxmtbYSz12QzaThu+sc
gzE2tDXReESrdPMOm/C1KWLostX89ZP25RmbXMttHnpeVKwzOLk6yYSvXJZUP4bpGHd1DZ1a
PI5uS6t29XKY8HOQTraNm5FSz4wWcGOxDg56vqXdz/Xgiy8hXrXrq6PQeBN3uGqX2OVVO7C7
tUNX1+wyrhFVxIldXrMz1ENmx66u2XVFa4o7doquu15ltDOZwZ655VvXSk1Lqb2CzhlZ6JtS
s7veZBxjQ1vVeI9U4llbumEZIHnRFF133SEbZaPBxF/7zERgokle9EOF0NdP2pdnbFIItdCo
oejiv+54zW7OVsV1zW6UTqu1akghifcKdDNdULIbZdONemnN43vj6ALPu2T3e3vwoQNjB3at
vNOte8cOfwd2dclO4ILdjBn1ZwbLHV04PrCry3VSwGHPA7t6GLAr2JA9sFPE3XWbzM50BnuW
NZEOfMyt9hB5qGHkLAe+60i0UTZm1qxy5ZZ/okW7OY4oN0/cITa0edyTRtKq559o0W7Kxuxl
e/nrJ+3LMzZZtKsZziDEhSvYX57kwHfdX/4YpmPiJZS3mFftYOdjVn/5ckHkc5BOzc35kj7w
bqWCowyjCyK/urj7IQZ8aCr6nET0aase6y340FXeA7t8DrCA++Qv6PIesYL12AO7VnRKPNHA
ILkDu/T9s74pg+f0A7v29cV7AroZ7NApkvOqAhdC4MyNsGe5EZWscVMnIUFNj7Y6QQdULddh
bWNsZKN4bpqW+LJLB8u9edEMyenXYW1jbDiXeLsWCg1AaAGOJy3xXna9v37SvjxjU3LQuWVu
LTuXAvYyypTSNcUH4nsftYd0alpXOXE3agXdF8+LZrDxm9L1IJvcgGxdtHd7GTBibN5t4lnK
7ie58Cla1zmwawWebB0dYzuwqyVeJ/CH7MCuFfC8tYqaaO/Ype+fl6052DQ+sEtfX8scV7Dm
fmCniLxrfzQ70yPsWXqEtmZp8p3+xA214Jrhul31svf1MchGttqyesVZjXPGSldx0Qw27jd1
xUE23oOOdw/ZimYsTSor3hgt2xkd8YhMfEfNlTMdTKoIvsE7Iwnj2trkY5BOzVYGh/r2kOHo
xmFeNGUU8KaqOMjGSgvtmGk4RcAMmbhoqAP+1ni/gBFfnE8w8XRgV4s7d9Ag48CuFncNzTQ+
sKsHAipqHnVg14q7tmll0Ahyx66u31ED+3gHdoKAoMuaVzxzz6gGexajoSUD2yStJpqhya86
ZyLw2oZvjI1sZi1DtDpJ2sWiNnxTmsZ+Hds2xobT0aR3qlVc0FRenuRbdznf+PWT9uUZmxIn
ArdWiLtrCAlU3c3wSLxZjfgYpJNJllK6x+2RB4YmdU7Gyc2ix+DN6ZVIapyKjA1ckSqDC19v
dffr2PAp+it5YNeKPNtUQRFwYNeKPN/EwK7XgV1boaVNwKHKHbpWQvkWDzdQQu3YtXe3hM5x
8AWe4BkVvJssDTvzGuxhlkYxUo7XJ8pgmSgumrHOq+VmFn+QTevcKnnphUEPPp4z5uiXu8mf
g2R0ay5VW1UKjQc6Zk6qeN0k89oZ1vCITE74sXDp0ksVAYurk+YC+fsftMd0gkg352K1txB7
qCqa4ztzUyseolM3Ya7xpYmDXkWHNfKit8b720sf6y34BAzDO7BrdR1tJuCq/4Fd++TXzQg0
uDmwS+9vvieg4doOXfruMW+Ohn4e2LWvj0IOgSM3B3ZK6e7aWtnOlAZ7aJ2v9EoC8NYMHMLP
i6aouhuTliE2uZfbJXcrieUVF4yNEk4xafGbesogmyK5HWHc49ergkMog7FV38x33ZwfzpCG
R2zKpuKq0ipzV31Fb/8/AAAA///sfcuSJDmO5BcNhQBIgPyBENmIz5jdwx52+rD7/7KAGy0P
U2JWaiwGM6rLu1sq+6DMcjjNjUo8VBEitGY2+W6YdzKc4D9O7HJVv5PDmjNLpnmvw/maDseM
hV81ZnKuCrdGTl0i3sTuRwjwZXRg8QXdXZplQ195B3Z3aZZRD7KB3cvuzI9CUAB6YPfypxqV
HIw+vaB7P12LTjpQSubALmF3NxJ8pzmDPhPM9/OJrfWWK1W832ZFKbPmm2rZVDRO1FoXZ0K5
s+SC9hCu6brjG3Y3GY3UyAn16ntEoDBALFrC7m7uEac1w6NoXvLKZBK1zOo/B2xzlskrXyt5
z4bTivbGXcWkgbf4vEgf8a4wOxlNz12s+LsgxDgFkwV6V2b/phJ8DeRNA7s7a2do8Whgt2ft
0Gn3F3R7zg4dWxvY7Vk7ARsqB3Z71s5AcfmBXVGL5Rted1oz6DPbjFJalsxOIfpLy+KHZO2m
ookEXEhNlK69ogPNy7J21763s9HkWlorYloyod3Fq7J2f/qkfTyLJrJ2pRfWTCKCXtnyIheQ
u6zdZDiNhHoWlRxk6Mck7SajMRNhZtMw4QOlON9Ju7+1BB/cLDawu9N21hRO2wV2d9quoImd
gd2dtmsFleM/sHsJVEmKShi/oFs/XQmpBgIHGA/sCnp3o7BspzuDPfSa6EqiLNlqYZTerVFY
btd2BnPROFMjrqzWrfUK+4ituFo5vbv2u52NpvitoOeqFq37qMfbCmUgp3fXzXZ2ejM8iiYS
cLWpb0yOeUywTTovsTW5pXez4TTSFinI3HpXOJw19r2X6fuv6XB6bbVotlKjURUN599TYpm/
Q4UPHFzYPLOA9lWuuAEv4MK/SRnQ31qoMKCt6Nx+6DTCaE3nwG7nwQ3MTQzs1t0l/1LgCuwJ
3s2EW8O1CwO79fN186cKbOMZ2CUl7BuGcjpa2BObAf9oVo3EmuRot8LmzJbwrXsuPBVN0Fql
7mw4l4paQMTk/BIufO0QPBdNTZ1yqzGlISUzxuzrEoc/58JXVdJfT9rH070p5i86/5qEM8Oe
eGXFGA23a3HAuWjiehutieKMuGdUo2iV1uHdtWsqHAohSvNYqBV+YCb5b8mE/1HqgGA28YDu
JXk1tYxayB7YvSTPUu6oNuCB3UzyShJ49HmA9+5wT1TQHT6we0leZGLALs+BXULybo7e09nC
nrgNWIrB1eoEL4y+QL33WLSknn0tIDMXTWRii5++Jv5P1FRnUfrWLudxvyajqUmyqNXWqnID
3TPrpC7vH3jEtVWwnb4Wj6JxvlY791KolpLBIZQopK0geTem1HPR+Jln6nSIVfxB44Y29q0Y
RuPcroeL58Lx34DvjXWrOceMEPrD+bc0HflHyAMqgSmUgd3N71RwfhfY3Uk8q2AOYWD38jux
0KwDz78B3pvE06SoAN/A7t3hHJ1UYLvsCV7C8G7O3dNIwp6o+7dEXcIGPueuHZw7a2tmN+4m
UeaieU2iGHHoJjPqVbBqEkWvOxbnotGUM5H2RiWzgFWLWPStmaJfT9rHs2goObsTija/ag20
pY1FC6J5mfLdP2kPo/GfNIUTuJQe8/lwRXvFVf5WPmZ2cwr7a6BVKayo/EQsejO8RQzvN0kE
shh4qz+we4meplYKSPQO7O5EXhG0y//Abid6fnKATHSA9xI9TrC78Qu6N43Xkilo8jGwS0je
zdF7GknYE3l/S6220smPXyOD03grSL+TvJta7VQ0YYVsZqX3mH8AlZMXWSG/tICvTt6paPx+
qqWqmLOIzODLpC5q9LsjeaeRxMO96c5UrbbsjxuD+o2xaEWfH//pk/YwmpyKX4xqF6Xut7iM
pvGWZCWvfem+pjdHmpZGMT3dC5jgmfWle5O836wRCNrfHtC9tI6TNbDBc2D30roaGlLgz+PA
7q2+l9RBDbUDund343xGJ8kP7NbPVyS6o2Dnu8AuIXU3wyingYQ9M5AoZpW1kR9NBpp7yKoG
vCsDic/JaOJsKrllEXKmWtAS04rrCpnepFOmovGXlmntMZxr/gc6jLLC5ptf6pf3T9rH473h
RtWy+b5nsNLsi1YIP3O9yRFPRRM5uFDUDMWiLA1MefuqFeG8Ktv3j9rjzcnRsyr11aeBeg3P
aQK/Od2PkAckUKz8gO4uzWY0wTCwu0uzgo6fDexealeToe3nA7v3++upC3oCHNi95I6csIEZ
u4FdQu5ujtzTOcKe2WD4pay9FGx7FrCD3xetMfW4Vm2biyb8j5s0o0rdCCZ3SwxXzK725msy
Gk5V/YzumZWECLZMXpIUuiN3p3HEw70RLtz9SWuKXttizZKq7E3f3VQw4VUqoTNu3W8RneCE
3YpZEboUgf+aDscv7zUzlR7jFWjD6lwDwJvc/WZ5wIImJQ7s7pRdBxPGB3R3ws7v8CArObDb
E3aoZcvAbk/ZCWjqMbDbU3ZVQP2YA/vdKbvTOMKeiPlH9q02ElbuBZ0A8kUrKpelX51On5PR
RPat5m711Z9WsLN2tpz0JGU3FU1k35rl1hvV0hWLhid73J+wutM24unecLWWueWOllp2ZOym
gomMXXgLF9PGnBmepvj2jN3k3mTNzreLf1OVwOTwO2X3txYHRLt3D+julF3cmNCUXWB3p+xK
w1N2gd2dsutg3v2Abk/YKSg3MrC7E3bcQeo+sN+dsDtdI+yJlL84rwlvsxChywImhWQNGSr9
RqRiKppI2BGb+tPQtMDt4LxGGvDmwJ2KhlPNpTc1KyYCStXEou+mdqdpxMO9EQ4BkdYti4BD
UssydlfRfE5GE7k3qixGHhMR+CLdkbGbDMfvQyTa40GjDF6KfNXUqfDTyZ18hzIgSFVWsJS/
sQZfA0foD+hewimpdzDZ9IJurxCjxkIDu3VvO4VpHfb1DezW7081KYNazwO79fM1f+DR29jA
LiGcV6TGacBpZ2FPPAZqqtpbZT+fYggCTC6nukKapfSbwt1UNCVl1ewcrfqxiY6k+aIV0dil
xtvX9N6Uxq1W355StGH0ua7Sor7JWp9uFo+ieSX8pZrmViImdN5mSfZNbgjnZDTBzLpm4864
9eKKisK9Msvs3mQybTG6W2D1vfYuEK/idb9Jfa8w6HE/sHsJnqYOTp8c0N0Erxs4VDywW3eX
mJz0gkfgCd6bs6uJFUw8DOzeHc4WknrgFg/wCpJHV0Tif1A7TS3aE6MBS9TslRzx/zKYJrVV
6izXR+9cNOxfdEj1aHOSUkDlW17jemw3R+9cNH73K9x75EmNCHQ91kVE4kZ/r52WFg/3plCX
4rtTS+aG5khXvBtvjHU/J6PJqXXflR414+a3FYyBhx3vkqzi9X1idnNIKmkoNFHTgo4Tzd2s
3zTvB+jvFbBn44Durhd30NHwgO5md9bAbMjA7mV3h5zeE+m9rd+fWRK0G2BgN3O7kjKYURnY
Jczuij34eXtaNLQnuvktUcjFqHb/Cq1iAfmiJdO7/VpZeS6akjRb79WvmiYdFL72RUvqxZfa
bl+T0agT6B4nrr8dOIMDopr4u3X32unQ8CiakNDrLytacd6NNtKkFaoBTHfMbjKa3CMNGc2A
TrrR6jct2Ru5ds+YjaaY+a+/9uzEDnzSaDJR/CZ2P0h2L4M9WQO7l+GFgj867XFg93IA88sq
mOt+QTczvJIaKgp4YHdn7wweNTqwe3eXJBJy2Pd3YJcwvCsW4efu6c/QnnlnmF/NxPmdNOkd
6wSKRUtyd9f6LHPRcFJWP9xCQTAL2r6RdEER0GnYtXfGXDQaEwWRqOGiIXoLMrw1AwWXA8m/
nrSPZ9GEtqE/YSxmWRvvFERkoWvRvbloctLC4k9bzL1rAetcsWoJYf3TR+3x5tSu4rSeo2MT
dAIhv0+9Kd5fnvbYLronFZ3zOLC7++6kgDWkgd178Nekht7oDuze/ZXkryR4CjWwW78/cS6E
DmkP7F7iGW3OWKLrgC6gDlSu++7aacrQnllMWCk9v3Tynd7B0m5LaN1lgflzOpqYHslh/5Gb
GlqSpQXJIad1V8mhr+lolEqOmeRQuwYH7nlJGvJmTvTXk/bxLBpK2YMxzV2KlY5Ks6z4VXOW
a8OMuWhy6KRGpjtTfqW8QFq34jVwO+gxG07v/pxlE8oRFnZfjVVvXvfXed1vmuLNBT3+D+zu
rrtcUXp3YHdXZoVA9+6B3dtVWVIntKvywO7OyuYCdt0N7F56Z6llkH4O7AqCdylr4sfuacjQ
nqjk+81H/ZQSbVSrgIlSX7RksOLGiXQuGkpanbBqKVKqEDrJu8JegkyuzTLmouHUuefWVYkr
2oSS+hodkJu03WnH8HBr5EW8SzbOhvas+ItxSRLyWg1oLppIwInUytaLMPqiX5S2ux6v+pre
nJjirdpNzS966O/m3XK3gN5tl95TtKAxsLvTdgXmdQd2e9oOHad4QXez9q5gv93Abk/aCSi7
OrB7WR2lzOD2Dux3p+1OR4b20JGhWKZSYjIzM9rfbisSXaXfTFJMRkM1R3+aU9UuMBFalLa7
9rmdjUaZ/bCVbB4VqJkRi747bXcaMjyKxn8Efnclp929UVZYtHfNuOxN2m4qmuwXNWuFi78Z
C3Wwr2VH2m4ynNfMvGY14cyg5uk7bfe3Ft8roJrnAd1L7moKG0t4mqKvsMN+KL6HkuOB3Zu0
q4k7mrQ7sLuTdgU14B3Y3Um7AiqQHtDvTtmdjgztmVuGqFThkp1CgGW/WLMkY3dtljEXTCTf
GknR0lrJsIXqminZu4zdVDScWnNqZ+wUr6I/hDWtaflSSPDXc/bxdGskMxOJaOeGqmr6ou/O
2E1FE7m36rchEjY2AW24fdWKyZDbjN3k5hCZxcRvloYqZPmiqVvET2d236K8R+iACq+YUls2
47Fde89gQdsDu70LkMEpsIHdXiZuqJfHgd26vxqdmwbOBB7Yrd+f9lQFPGgHdu/n05QZPGsG
dsHLhOmqsOpc4PSLaM+8PKxUZclCbKhcj6xJKNZLhYnPyWhK4lKcA5hWbYzeCNKKFheydjNW
ORmNXwSc1ZTSnHOCvVllUQruUk3w15P28SwaSuxv4eyMSWphMJcRi5YkFG9Y52Q00rVma6Qx
54FOvH6vFvfXfDBcu18GilWzhk7ezPms/HTO+U/S31NCTVoP7F6KV1LPCt61D+xuitcL4wp8
ZYUR6DOJ5YJSqIHd+v1ZVDHAQZmB3fr5miSuYGllYJdQvKtxAj94T9+I9kTMv8ZR1bKzu6zc
K9axXpecVU7xbg7eqWhKota7Sg3OamD/fVmjJWjtJq84GU2nuPu1opk7OnXni5ZQvJsE9mkb
8SiakOTVomLM2UTgCd4l0dxRvMlowg+wt2bSioGWHos4Hl1WwL+mo1G/GnXSQi/HFTQf/+4E
XMTxtovvVbCL/YDupnaGelO+oLuJnXWQGA/s1r1tnMwqtrkDu5fYtVQFJO4Duzt3R+Bv44Au
oXU3UrenO0N75jURxTthNc5koPhHWTJFcC+9NxmNmnI9dAQzKNzri1ZQbrMbpdupaMS/5tpb
plakMGho4IvWuDPcSACd7gyPoqFEVnJl/6FmVpg6rBCsupfem42GpDs7VSJ/2lCSSmtI6s2s
+FQ0fi8Wq509FKlOutF5lblH7c3rfo72XmlYseaA7qV3mirawDSwewmepQIayx3QrXtLxCmj
ftoHdi99Mmce2HvmgO7d2+yUraBNTQO8oh2wXBO8fjoz9GfODIVaZT+pTK2AeTtd4mVANV93
4M9FI6n1SNgZt1zQYqYsaaEj0+tjd3ZvIp9aKERApBGqvLciQ8yZrxsC+2nM8CgaSlWdRIjW
GC6CGwJXmPCx/PmT9jAaJzc1RqRyK1QVrYDkNVLRd+LKs5tTmv9guFvjXCu6OW9x5QWjHtuV
92oFf30Du5fWhRAqOOA/sHuP/hqDpfAI74py54PdFUrWsUP8gG797kSSGeh4MLB7Px+niqo+
DuwKUsfXahn9NGXoT6Tyna6LUGvSLISIwUGCFS1dzumuVVlmg6Hae9VKGvO04PxXWtIKae26
C2p6a1ruufptWQWWKljE6S7rfb8etI9n0eRkof8TJhNV8LyQreB0d/O7s9FEkZy4sl8dKtim
umh89zqar/m9aZLVHzQnqLmjontzLdhvSvcjRPeog932A7u7HssFHWs7sLsrsvzA7JZ3m90W
SdLBfOzA7mVPTndflRSEPR3YvZ+vx4QEyO4O7JKa7LVJVT8NGfpDewlVIzI2P33BB3aRNeyr
3ePq0J2MJoiqhAZxMcLlWda02l0PVs5GI91MpImKOc0Do1nTsi83yeHTj+FRNKFR5NxOS+2N
ULn+ZfIs18Pic9E4UyvSNZyInatm8Jocq765KDsbToxScNSX/XqE+njGqjfB+8sEb7vsXgUJ
/AHdnbEzdNx5YLdn7DJYKB7Y3Tm7xgUcijyw27N2ivKmA7s9a8dgyWJgl/C6q/PJT9vTkaE/
c2TI/ib3xy9TRWUOeYmFAdVLz97P6WBIS+7qX7blBs4u7sjazW5NK01blawd7YrdkbU7/Rge
RfPK2nkgYballcA2ix1pu8lwGpE/aM1/NJkarFP3/Xm72d1p1KOX109Kv+ehvO6duFvB635T
4o5BXbYDujttZwWU5hzY3Wm7kvFBisDu3d2aKjiAekD3kqcS5mbYtzewWz+f32dMwKdvYJf0
2d10P51uDP2ZG4OZdbXChRSvYq5I0VO5FA35nI6GwqBKnAplFkaN3Va0t5Pp9XzsbDS1+K50
/8/L5BaMZsXAE+dLv95fT9rHs2govUSIQwSldFSpjlZx1Zvq/1Q0TtM4d261OR/KAv5wYtWC
cO40lWfD6c1UKURdWiZFc5D/nprK/LdX3nvEU0CKsuAduYAK/y49QNhe5MDupcKSCoGZpoHd
ToUV7AAY2K37yy34N7jBJ3h3DbuhNmYv6NZP10vyIwl7jwzskkznTX/iaWLRH9k+WJLOFI4P
L5MRdEhKVhR9X013VxxlKhx+ja5qbr3UDltyrJhcJavXBiNzwdRkVNiaWViUCVZ1ikVLyPC1
LFE/PSyeRuPMUamYE2ICm2d80YLfDb9Mle8ftIfRZP+au7UaTZfsFxbsUfNVS9xf7CarPhUO
pdbJHzThriygzi5NTmv9dC78T1IEjNs2qggY2L0kz891tI1tYPeSPEsEX+sP7F6SZ5aYYfPd
A7yX5EVPD+hOPbBbP59qnMGw7HNgl9C8m5zn6WfRH7kMaKLGbCQ1KlrgLHwsWkLzblJRc+GE
D7NwmFrUVtHZeV+0guf1a/WYuWhi6tkfbI+m54oKz60ZlXaed9OpeBpaPIqmptI1sxCL2euv
h3heXdF3yZcc/HMymtDBpVLMGV5XbWAvSKxasTk3ys9z4YTyMytly/4ysAIrP78bFRfxvO2q
gFYJlgUM7G6Ch07w8qIJ3oe6gBW9Cx3YvfSuU0JbwQd2L7lrft1FC9oHdm8OLyfYd21gV5A7
vnZa6KdvRH8k528puq2cOYjWDH7hr0VLyN3NGMpUOJyEiDo3Z6y1o/oDvmhJEu/mxJ2KpiYx
pS6RW7GGej6mFa86/z3dDDydzhGPoimJOGsjo9z8GoG9e8qkW9kfsl7X9jFz0WR/JRpbV+7N
GStYrvFVS5RjLn3+vibDocQmfoMofpvQBls481T2+03ufo40oKCV2oHdy/E0hr1gccDA7k7i
ldLhwldgN7M8f+EwSOJP8F6eF3ki8Bsc2K2fzwQ3RhnYJTzv2m6hn+YR/ZGkvyYtvdZCUhiU
TI41S7zbLvWsPyejYSfU0q2YtNy1wdI4S2q1l17OX5PRlBQlUxHlUhStqfiiNbXam/mn0zzi
YTTZWNT/0TuhCYSyZG9Y6g3Nm4om/A6C5nFRLc7D0RxeXTOVctMWMBVOjIJ3qVw8IiXYi25u
FPxN836vQKAwKjNyYPdSu2ilB3u0BnYvtYv2EQW1Eg7s1v0NOWIBUwIDu3t/SdHx1wO79fMV
DlFM8HQ6sEuI3c0U6Gkf0Z+I+muY8jYtGoefgB5nusiU91IU53MymrDE0lxFrIf6CipVUpbk
7/rNDOhUNJzUOVATZxBNpaHzNbZERuZyevrXk/bxNJrq/MfYaUPhDGri8yLl5xvHtrlocngJ
SRdt/qxxA4ef8qJxoXqTv5sK50XsYkS/ZPN/oF0Nb2K3gtj9pmnjXMAX5MDuLs8S2v00sLsL
tFLR1N2B3czvJFWwSDKwe/c3x78SzLwc2L2JxRjcAcVfB3YBh7hx9uA83CPi/zzhdyJc/K5e
ai5oYUYn/db/wO8uxdsmo6HQPegU09NcawbzkImX6MnYpXbbZDTxWmUruZiGogzK71Zo/XC+
jObXk/bxNJqiIXvonNUZHlo6X/Ha5nw9zDMZTE6l9ea3oqxVWgc9ZHzVksbIazWZ6XDCOTQa
cNl/lKhaaKx687u/zO+2qwSWAmqwD+zuxE7M+6CJncBuT9yhUiMDu5nYWRJQMWBg9+6v+HEL
D0fzZl+ZIqE4Df46Duz3pu387DqpwxNZf02N2VlDqCVXtBCjS/Qw/N93lRr6nIzGX0PWmGKu
QpUNzT6suBI4b7+sx05GE9UGKqX3Xqufthh14EW6etdpuzOaj6fR1O4kqFDX2gztBUkrjCxZ
rh15J6Pxm6TfhbpToSrSpaKyenUJTb1O202GQynXKJb7j6c6uQPLOb7oTev+Oq37TWm7ouBT
O7C703aloWYEB3Z32q4yyu4O7GZ2V/G69gnezd+LgWKxA7s3cVec5cBKhm2F/NN92o5PDvFE
1l+ThBCdVfNjt6NTwKvGKq6Oqc/JaCjy3+ZxUKOaQQtbX7QkbdevJoC/JqPhRNE+mGvurRSD
lV7W9Ntdjmef0Xw8jab0bP6eI9Jq6EjXmkQX1xt+NxVNtCB3av60aSEBJ4CjlvvdabvJaJrz
waLUWic/i1Cll7lr3k/nd/IdOoFgC8+S7p1lwx7b9fiaP3yoHl9gd2ec/KhEM059TkTzLxWK
0b7fgd26u+wsSApYKT7BW79B1dQVF0IJ7NbP18MtBrxTDOySnOKlZLCfRCeveWI5QL63L+dT
LoULONb1WrSCdF6OJn9OhlNSjhJebuK8M6Pvr5SXWMrZDemciqYmj4MKVSml5IylSOsi17JL
2Zlfj9rH072xnFvR3As7WcNoWlnU2Sg36eupaPymUoT92uS/bM6gyn8sWlLHv+qh/ZqOpvvz
26oKZw8LHeV9G8otY3e/S48PNSIf2L0kT1NTkOS9oLtJXq+4+0hgt+6uZE21w2J3B3hvYdaJ
kYEfcGD37jCxP/SoqPwAL6F5N31a5WQSj5whmhMj7qyirYuAOlxtiTWE07zLRvzJcGJIQsxK
dmLkBxfaRLfiBUHWb1oCp6LR5MduzdX5t/8BEqNYtITmXU6Nn9F8PI0mmxO9ni2TR4NmsReZ
kNzkFqeiyan7xlgz9ftRN3A40letSPzS5XXvazIcDslV59+ZjQo8Spn4PfKxiOdt1+PTAhrn
DOxugofqhx3Q3QTPFGx+Gdi9WbwexXTUUGyAt36DZqkx2Hk3sJsJXkmk6HV3gJcQvJvacT05
xENfDfU3ux8ZRE1QwWVbQiKo9Euxlslwir+LJGePhbhVsBM/Fi0heJcKGpPRaNjUZj91xbKi
AvO6yKX2ckL516P28XRvqLHWGiM5TUFdoLJE2pvpjuBNRUMvr5ws7D8btoy2KdCKrCRdeuZ9
TUejVHsvjaSKVLSpdq4h+83vfpAkHzhJdkD3kjxLaPfdAd1LASwVVBLlBd2bw6P+wKR3gPfm
8DRVQ116D+ze/eWcnBehxpAHeAnFu9TC5awni3ikpd9CqNhf7jVTbg08qdqiUm2+KaBNhcNJ
1Xp4c0U3O0jxfNEaPb6bAtpUNJo6F7NeLETsDM3hrRAIcIp30xWgJ414Ek2J2Zzsr2LnrAQa
wZUlozksl221n5PB5KSVC/ktIteONqLmJTKWfh27uUtMRUOR+pYW89Y5ho1Qhvce6v3r0x/b
1fgYu8e/kLvb70TAxM7A7j31o1oI2rkP7Na9bRpu4FgiYGC3fn8iyQqokTuwe1lnDIlnWMko
sCs4Xb5pxLeTNjxza6ilWW/sBxQbbLm6whCAXt1+VyftVDScKGplyo07oY9PLFpB6e5Geiej
Mamdauncq4GUzhet6b676QCwkzc83JusVrhW1jAI2TrAcjkk8TkZjV/TyESdzVVlBT11Zmck
nkz0TkUTmnrNau89CzE4SUmTmkBvTvcjhPgYbG4/oNursgWV4T2wu+uywqBM28Bu3d3oBBMG
p+pO8PbGSlQIcmD30rueuIF3nxd0ScLu0tWAczsJxBPhfP/iLMZfW29ZGRRq8EUr0o9Fb8jd
VDSUtJRcc1X/uxs4jECrSrJXe/M1GY2kcLCrUpk8LMGSQr5oTb7upvrfTgLxzNtEa3NGVDI3
IfBeFAnYFSmufJOwm4omJ5VasvbsXKgpmGbISx41/6Q3A71T4VAiVaMSwy+saN4+0dsm7a+z
u/0yfAL2Yw3s7qxdAcfjD+j2nF1FJxAP7N6cnYXVGfYyGtjtOTtroC3agd1L6vyRQi+3A7uE
1t2Io/WTOjyRza/Jz9qeOzUqRmDHUF0ijnafs5uKJtJvlvPLsMoaqDEZ3ivfnbObjMai/Oos
qDh7INg9Y4kM313Orp/M4eHexMg3O00tCt/IN+TspqKJnF0NaZNexPx/qE7L9yftpsKJ/Jv1
bup/NRF4rL5l+P7eMnzoPNPAbk/bMdjoNLC703ZoTiyQ21N2jNponuDdXZSo9cgB3Z2wI9hZ
5sAu4XbX9Vg63RnomXNG4zCs6kLN/4RTdkumKNr1mOxcNJTUnAlVZ42vP9GU3RKJ5ZuU3Vw0
nHrrXK3nMDMAe3Z90RJ3hpuUHZ3uDA+j0aKam9BLUhBuf1zRlfZy6rh/0h5GE+1yWbPFoVcE
9UVbEgzfDFHMBUN+JfIfTM7Nqr8N0J/N3IHw05ndtwjwEdyPveJVtGy4Y7sEn6GtDQO7O5uI
FukO6PYisaBevAd2L+P0Levo4MQJ3voNak+KFi1f0L2friVFBd4GdgXjlGtVNDqNI+iJmr+T
4ZYrWbT/+dmJ/Z76kmlKZx7X+ntz0ZTEGqK15WVfa2AJf5FX26WUydd0NNS7WDbJ0tHbgEez
RLHuckTl15P28SyaKHn7I8atFioVzPTGoiXZxJu7zVQ0McfYc23aJTOjA+9LxNI9mqvfzdd8
NJF85wiJQJEZXzP1EvjpjPMfJb+XwSGFgd1L8EoCH8UXcje962BjyAHdurMcNiKgytrAbv32
jBILWCoe2K2fr7VkFax3DewScnethUanawQ98sDgZK1ZEc6NYAsanrTg/AO7uzlzp8IJamNC
oTAh0ipW+fZFKwaQ7bLy/TUZTU1cOBoaayW/vYAyqGmFBqWzu+tmUzptI57uTa8xdyMlOhrB
VHySNXzoT5+0h9E4USNhrWq+QQW004tFKxoaL6P5mo7GNLcSNxRCBW1jzZvdrWF320X3DHQp
P6C7SR06yhbI3aSuweLjB3Zvzk45gaYZB3QvqWsPxPbafrE9J5JmYD57YJeQumv9MzpdGeiJ
Vn5P2nLmqn7MtgKy/L6mqnqntDcXTfEPxv5dB6HLYPdtWVUivu7Jmg2GVaxVKz3sUVEStOI1
wvmSoP560D6eRcPOzoo/YKUYhyMgWCJeQumuR90/J6OhRFSs+f5Q5w66V9OqZsZrGZbZaELd
urBUax2U7KbJ8aE3pftBOnuo3u7A7u4ArLDswoHdy+8soZKUgdybsmuUuqBWmAO8u+JZqoAF
2QO7d3dJkhbUxniAlzC8a/kzOg0Z6JFbhoYorIifVZ0JrS3pElFYP1WuG+/nwpHUcy9EpsVy
RVV9llgYkLWb7qypaDS8azOZ709WBdN2usa7Nl8y1l+P2sfjvSm9aIv5Xaet2NvRFy1pA/zz
J+1hNNk/WOvi94nWjRTtA1zRKH8rpjwXDaXanav6ncspeAVbM2hy0OtN8n6v1J6fRfjgbt5s
RMWcFO2ZHNi9R3/1wxyUsxvYvZX2lvyNhKWeBnbr9xfjuGg5e2B3f75SwNTdwK4gdnRD7E4j
Bnoij+9fXbUYtKhccgN9w2SyEvMHXncVzedkNDG6250CaW+9CtiquWh0t122Dn7NRyNO6opm
CQMTeBB5STn2rvJ/GjE8iiZqkb1XFaEsAieIVoy8347uzkUTo7vqP8dauYlVwqpbq0Z3L8P5
mg8nmzpD9SdNMoGDUXnSkOXN7H6E4F50RaCzu4HdXZVltDY2sLsrswz2Yx3QrbvbOHEHd3dg
99KnmozAuvbAbv18xV9tiqopH9glebtrvQw6TRjoiTZ+TbmK9pCnExNYTXlOkuG/0zu+OXSn
ovHXUHf20Ft2CkGoD7YvWkLvbnqgJqOpubOEWkYXBV0YeEkVgLPdzFKcLgyPoqHUnQVV/4v9
t4D689CatF2Wq97Bz8lo/Cdd/BIR88i5lK4wvVtikfHnj9rjcLr2bFJEpTYFZQl81Vtx76/T
u+2Ke2gbciB3J+0MVSl4Qben7ETAXrsDuzdlFyohYD/SwO7ldCXIBvZqGdjtKUWzB2qAtqYW
e6OTcbow0BNtfP9oTaIHvL5klEES7YtWdNu1m5N2KhqnZ9aYmoUWLOMOGSuiaZflvq/5aJzP
VVJhaYQaUS9JQN6n7E4XhkfR0EtyMkzpam4GKhvsSNlNRRPZqt6NKPvNpBLYN7IjZTcdjgg7
2Q6HazLUxe2dslvB6X5Tyk4yKCDwgu5O2FlFu8UO7O6EXRGQngzs1t3tOcVIJNY7f2B30ztF
9fYGdm/KriRuYMV4YJfQu5tEyunDQE/E8WuKamwkhtS0MlaJqUusRsN39vrQnYomTLZ6tuBE
RayjSa4VPe5O7276nyaj0ZefLXFuKmA3F09ajf4hK3QjtHPaMDzdG3byoNSzlgq2qUZR+rvp
3VQ0L3pHnUlKVhJQ6XqDmPJcOCGmrKpUoqPTwJmqv6uY8j7u9n/+9V//+n//+q///Z//4b+n
nP/jf/6v//ufW48p7NaxW4cYZEV/+qn+PwAAAP//7F0Ljuw2krwRwfzxc4EGtvv+99nMEvUW
mIHkEM1m99o1Y3sMTBCvsqgSg/mJ2MK+f0h6sCioTDOwe9l39JiB+ziw+9k3WFAd2N37y4Qa
EB7Yrd+fxXA3mJwe2L37K5ZyBr/AE7zgdUJ2w4pOwwx6ZjHRu4lzVcrshBjtiMxLJl34qgHg
czIa/6lbKKg5/eZSwIZuX7SmI/Iqmq/JaJr/8Eq1UlWsVzAaX7SC4l1XZf88aR/Posn+pDkD
d+rtV6PWQcu9vEa/+3pG7HMyHEqkUZSwquZ3JFShZkm7qlxqQ35NRsOpUpdMfm3lCt/05kpG
P02/f1dy9Wf1B6lXWH8wsHtZnkXbMfYsvqB7OUBNuaB2dQd2N8erDfslH9C9DK8l6eCRNrB7
d5d7EjAdObBL8qvXsnB8mmbwQ9OMKM/mbLmQgRMvvmhFtviO381FE66AuWUq2l/t+yi/WxFN
u/S5/ZqMpiarTlL9HzXUf0FdibSiUeiW3/HpmvEomhe/i+ZbrVydfcDDv9/N7+bCCT8PYS3U
ndhn+14TkP/Mr7Zrrcu5aDgeNYkqmmWrjLrNzD1qb4L3CyQI/fkApdYO7G5mVzI67nJgd+fv
qoLNcwO7l7mrEzZUOfzAbv3+Sk/ZUHOOA7t3f5VTE1Af7gQv4XfXGnF8WlTwM1MHflnLRwld
YPdnX7SE312LEc5Foyn0Gp1La5bgeKB+34reEOd310mVuWhasjBBEdXeegbZalvSpn5Tcf7z
pH08iyb7aySHcHW33gxtbshLOnFv6OrndDg9ygalZpUQ3oHp6pJwLt8DX5PhcMriP5qmqgYr
ReapJ+1N736LHKH/uFCl94Hdy/JKauAZe0B35++UQQ41sHs5noUyL5ghO7B7OZ4kPwxA+bUD
u7lGW6IxASTxA7yiRtuuNeL4NKrgJ/YBkqgbU7HCvSt48MoSGzJ6sfirg3cymuLXzd7JJAc9
AqNZsjctX5sSz0VTU3PuYBwmcaygV2ws+m6OdxpVPIom2FrN3V91reRm4NsxL/GrYbEbjjcZ
TuvUnRURaam1wEMjS7QiL4fOvybDCc1ZsjAnbx4MWLiLRW+W93dZ3n49QkKFpgd2L7NjZ5Ng
d/sLuvfktwQ6j76QW3eWe4xSg6T4wO7d2Z4aqvQzsLvrxgaPhR/YJXm7G053OlXwM/+A5q9w
6hr3CgNpvi9aY/t7w+lmo2ndSV0OtTvY2mHFMeuU7iaVMhWMpJpbDsvf1nF+WpdYj12OaP95
zj6eBZOjscuI2VSUDdSjyJOtXf9Zlb3xl54Oh5W1dCXnQAorTC8J53rk/GsynJgep+Kczl8C
XDLojTDZz/BmdL9ChzB3cPZsYHcXZgnsejqgu8uyYqAN+8Bu3V3JkeYCJUoO7Nbvz/9MQw06
BnYvuSupGzz14dAl6brrkQo+DSr4mW1A8y8u8lvGuaA3kSUpIdLLzqHP+WhKFZMeyigGlmSD
3S7hdtdzpnPRSNLGxpZz7dpAxXpZMm7u5O5azpxPg4pH0QS5s1ylUS3mBALV7ft+cjcbTjDU
Li8n44Jz1TUF85t7xFQ45AeQUOsUlVlC3RF80Zvc/W1yt1+FMIO9NwO7O13XMyhSOrDbE3bN
wErdgd2dtNPcwHbFA7s9aZdB1v6C7k7ZFXRWdmBXpOz0htedBhX8zNKhFcnq5xP5Ox2mdWu8
Q24ydrPBtEaFcmGOUt+vSdlNRSMvzXSnDUYVtdFZlbG7mnH585h9PIslLOGbE9Tu/xPmYzAL
+t4E5Od8ODE647EQaWfQTHFHxm4qnPB1odZy/G6Mwbt+LHqTur9P6n5KhpDAKdSB3Z2x0w5y
p4HdnbMz1DpsYHfn7AgV8B/Y3Tk7IVTH+cBuz9k1cH8HdknW7iaXcvpT8DNHh1diSJm5K6PK
maktyD1E+9j1qTsbjXDrJbOZVFTxak00ja6t4eaiCQWnF++OWiYXjKzGou/O2p32FI+iCUYk
JtqCeRPYa7GI38mlPvvn34imGLP/IrNyzvBYyBp+d3OTmAqHkoQGYa+9lNAR+lcn7QTmd0/6
xrEHvqwohyyb79gvvyco5zywezmnJv+tw251gf2BOjHMOQO7O1/ciOF8cWC3fn+Fkxl4MA3s
3v3NkpjRBugBXsE67drdhE8HDX7moGFWggWQH82KDkulJZVv45ta8VQ0Ehya2JwPVCawki+r
WOdNqmcqmhKX+WaUu/+ngHp1sWgJsbkRAjoNNB5FEx5vrBb9DtyLgh2nec2kyiuBcv+oPQyH
kpNnNcvCpWW4yWLFQcTEN20JU9Fw8hBay2b+pFlDdePnUhG/nXX+m/T3BG3HGti9NK+k1lFX
pwO7m+b1gvZVHNjd+5sr2K44sHtTd5qogsZQA7t3f6UlraAJywleUTq+O3xPJw1+5j0RPfhi
rXeVDPZp8RK72Jh8vD57p6KJeWRuVBo5ZcUnJNYYE9O1s9hcNC1RIW3+d3RpgRO8bY3Q260K
32mk8Sia0NMLAb5WnX9Tg1Valqjw5cus/OdkOORvxUImTTs7D0dHXlfUaPyD3gg+TkUTLq/Z
fzCUM2tHVVrqPzK3+K8Q4RMGj9eB3V059l8UXDkO7G561xRMIgzsXnqnyVCPgYHd+v3VUJsH
O1QGdnPXZ05k6Dt9gJd0Bt4cuqdRAz+znfDfbq9ZSYp0QgnRiufBv5ebNvypaDRxaHE4CyZq
DO6PLrGdcHp3bWI3F01L3a8GzQmEkFRQ0SQWLcni3Yzznj4Nj6LJqVZrfhFrxTdJFZ5//XYR
vqlwnKkRVVLnd1lQRhSLlkRz06YwFU2YBRoXbk26bxHYkD1pCfLmd79Iha8/UOHru1X4auIK
0qiB3UsDalIDG/AGdi/Nc+qbCcySHdi9xdqcrIL9agO7neYJo2naAV7SInit2SKnX4M8c5/w
E126lhZiYmBifJkO31U0n9PRaKXcrbXcO+FeGksGe+lqauJrMpqWitMIsxpUr4DWgbHom2me
nHYNj6IJwtaLWI/RUa0NHppYksW7TH9/TofTLK6/VKUUUfCXk5fMTt3yvLlwwklaVKLtqveC
ZlAmVcrfPO9ndfgUVI08oHuZnSQRtA3vwG4++VOpYJvbwG7dXS5JKjhaMbBbvz/h8NzDzuUX
dOun05IK6h44sEuSdzdn7enSIE+U8ymVJtlKDPSZgtr5sWgFq5Pr5N1cNJyyqWZ+zSdmsJoZ
i5awuuuC2Ww00YhvjbUJLpu5yKPh0u/tz5P28SyanJyYUuE//wBp0IpW+BuS+jkdTtyCPJCw
we0Kpr0X5SL5RhpoLhxKMULu8TCJwm1Fid7qygtY3Q9N9hKqsfyC7m6+85sf3HwX2N3VWcng
PXtgt+6u5KTojMXA7iV3r3ommEM6sHubA3vqHfz+BnYJvbtWbZHToEGeiea3YlIqWYv0Ayx0
ssQg7VJ+4nM+Gu2tkIRAMWoZ64uW0Lsb2Za5aMTvfD1Uo6uRUIOtQNbQu6uRhD9P2sezaGKm
ldS0xFVCGjh/tmgSli4353M+HD/zrJZcG7WO/XA26LbMRROiyUJO60RKh91830LLC8jdfi2+
AvaMD+zupJ3fLsCk04HdnbSr6FDAwO5O2jETnLQL7O6kHWdwkHNgd6ftKoNDKQO7hNddq2jI
6dIgz6Tz/ZgVdipkVRXtH/BFS3jdTS5lKhr2CxypNq01SmWgVKcvWhBNvaz3fU1H0wtT9Vha
hIRm7dZU+65nd+T0aHgUTGTtnAI5ccg1F2moHt+KYtB91m4ynPDNUCtG/l1lOGm34D50n7Sb
iiaSdppjrrnFPDuqc/Quxa7gdT+UtFMCa54Duz1th44sDuzutF30L6Fpu8DuTttJAd+xA7s7
bdcMfP4Gdnc3oB+8cDdgYJf02t2k7U6jBnlqoqEhHJRjDg+dAlpjomFyPcY4HU0VpV6pd6OO
qootMtG4SdtNRSOphExn6xbJrgqn7RYkIW/yXH+etI9n0bwE7Jxnae+1oh5ci/Jc8tdP2vNo
uKqEuYn43RfMEC/z0LhJ202FE8rJrVkpJYeZDtqc8c/M232LHB8xeHXmFXmAZaMe2wX5rIEz
AAO7vRMQFVke2P3FYuycOKB7OaemoiBnH9i9nK4nLuAg78Bu/3wC/joGdgXn7DdM4HSRkCfa
/tGirc0Pmt5EGizGtyLBfDvGOxeNJtZaQ5e3+r80jNf4ohWl4tpvEj3T0ZhfprRQ5g6ytDXR
MF2mrf48aR/Posmp9NY8jmwtqyk837FglOiGpX1OhkNJes1+Fyfr3EBjeGdp3xvN19+Ipgj5
j6fULrAn71Qwv51y/qu0+Bi1MTiwexmeplbRsueB3c3wegbL2gO7vS2ggXW1gd3LoUpqrYAc
78Du3d9MfmaBL8MDu4Lj2Q3HO60k5Im+Pyc1P6tCI621yqgG1xJLOpOrqdfPyWgkTJD96zZl
kwZ60smSSmtYzl4fvFPRlJRJixU/eSsJ6hOwRg3kTnBZTieJR9Hk1JyuRoGilMYG/nbyEjVs
zpc/nM/JcJwVcWjwkf+ndvAk8kUroqEbm4+5aDhlzi8NHYrrEXrVmxPgfZO83yDFZ6DS8sDu
Zne1oUrLB3Y3u2ugr+YB3Zu/6ymjFngDu/XbqzUx2rMwsFs/XytJGfx1DOySlsArNuQn7mnY
IM9U9IW5VKLMBZ2ujDULgtF+7as1F4z6HaSyZa3GzcDhSl+0QmT5JRd1dd5ORWOJRLn2rtyL
gVPjNjlc+Z/s4dKP7s+D9vEsmpzMrPqzZiU3jwsVWV6hrHUrsjwXDvkrsZqWkP4StDeYEi1J
3112jnxNR8PclJuH4kEpSlT5Pce7itr9kApfF5BBDezuvsCQmED7AgO7l+HV5KQX/LEc2N0V
+I56aQzs3vyd+jMFco6B3bu/HAI7qJfGAK9geXd5ldOvQZ6J6DczUWm9F9aMKpys6GMlu7FP
nYtGUg35vexHVa4F1JqSJWaw1C5dub4mo6mJmodhTZ3kdTC7GouW0LxrWW857RoeRRP11nBM
czJRnXWBXbXLqrQ3yeLJcLo/wP6b4SaWBbzw+aol88l3ZdqpcCjVSlWpkN8rCFWimBxkefO8
n1XhkwzakQ7sXm7Hfu0GyxUDu/fstxBHxXX4aK59dn6k10/nDHK7gd36/Yn4d4KO9B7YvZ9P
cYXvgV2Sv7vRRzutGuSZG4CWbFScEZF2+I2+pDarl92En5PRhGQUFz+hWucMJ/d90ZIE3k1W
ZTaabmRWerilZTSaFdrXzuxuNB9Pp4ZH0UQCLyQSs/MgEYNnem1FO+HtTO9kOM0JUOnNmv9y
GqgqFau+tXL+NR8OxwXeWV32axH4sM1Wzt/U7hdI8VHqaIfyC7q7OssMKkwM7O7qLBuqBXZg
9/K7qBmC5bgXdDt7gqvHB3br5wvtZFyvpSyRa7nLpejpz6BPNPMpFTarTiGaszuD5VoWFACd
hl1XzOaicTaU/RbnpxRJEzAaX7Qia3cn1zIbTStO7krO/pdUtCdyxXQy06Xh258n7eNZNNmf
tB5Vc2nVGRHMHr5dr2U2nEalM3XNrbYMi0avMOsMJeS/etYehkMpXi6lizSjjM6eTv5y3tTu
Z4X4CtgZcUB35+yqoTJ8B3Z7zi6DSYOB3Z2zq7A89YHdn7MD+4wGdjfrFMFZZ2C/OWenp0OD
PlPND4nYEo3hwvX35OzmonnJvPsSbTkUidEWwjU5uxtPtNloOGcmrqHi1Auqw7ckZ5frddOd
nv4Mj6LJybQ4Z5CoX3aGBYm/PWc3G05Uyv0XE7JAcGfGhpzddDisPXfJGnli2LFujqa+id2v
UOJj1P7pBd2dswM/3Au5O1+nBJ79A7uX29Uk2mHH4MDu5nbNQHn9gd2bsevJDyiwX+HALuF2
14YGetoz6DPN/FKimC0i2So4guCL1lhnXEXzORkNp+yXzC4SxeUMVhti0Qpu12/O26loJOXc
YppCsv8T7IKURbOy5XpyR093hkfRhMdZab1HUtVKBfVJ8xpJwVtuNxlOy07uqLCp3yLAsf5Y
tSKcdhXO12Q4lKg09lueWi4C9qj6on9kpx1/hwgfOFu5YlTtEU8BKcqCN+QCGvxDwoAlg1Rk
YPfSYHH6CErHDex2KmxoNfDAbt3fLkkaeDcf2K3fn5XUO5jGHti9+6uawPMikEto8PXAiZ5u
FvrEYyBmYYxMs9NGbqAgmC0yCObrKYC5aMJSSIrFpVLEQINgWZOwbXRDg6eiaak6b1Qnj426
gTS4rXGzyPVanEhPN4tH0VBqjUtlqmExAw/irpDAZ76Rop6NJi5afnUUUWuwsfaKZLrf8/7y
SXsYDSe/neSsIXwONyf7onfhehWx+yFZQPR3eED3sjvzKyOYaBrYvad/Tf6SBF9jB3Yvu9NU
wBaUA7qX2zV8Yndg9+6utJQ7ekkc4BUM70aOV09DC33iMmAp/Cyqn1VaszHGImLRdzO8qWic
rInVHrORLTd0Lijpimja5ajG12Q0/tg0M3POyvxqfYQIXl4gg3NP8E47i0fBBFcTph7Ghbkw
mlFfQvCu84Kf09FQqfGgGfdsOMFbYiXXrtUn56KJJqXGOfvmKHVw3DQ6w94Ebw3B2y4JSOjQ
7sDu5nYFLLkd0N15O38ZwzZygd26u5TF35qgrucJ3voNlh7XY4zdDezmBtSWlMDS1QlewCBe
jRFXh+5pHaFP9PxL4lyKNsvSC6qh7otWDGu8yOTVoTsVjSYSClXhLr1Vwg5dXaKkRy8LpKtD
dyqanrRopag7+L907H3Xl2QjOV+2GPx50j6eRUNJa4j5FMsh+wy+fdKKrAFTvnb1mIsmpxif
8T23Ek19HR2S7iu4N13ObH1NhsMx+FhL2MhkU9hie24a8c3vfosuICW/2WObPbB7aV5JLaO9
dgd2dwpPGU/hBXYz0dN0XG0honeA9xI9SaD2zgu5meRxUnTO4QQvKdLeZFZO7wh9Iuhvqdee
Ww6/YKaCFmn7miLtTa/iVDSSirSWtUpxkgfaEvmiNSm8m9LZVDQtVbVecs1hS4QKjU9mVv5r
vvimV/G0jngUTQwvFfHXSBcraJtvMMMVZU27IXlT0eTUekxKc+mFYWGfWLWEs17LFM2Fw35R
1latSpPaFW3ynRPsepO8nxUFVNQjaGD3EjtOfhfEB4z79vxOqrCnx4Hdu79+nKHF2YHdu789
tSJgleDA7qWdnHIGb7kDuyJ7pze12dM5Qp+ZekTjee7N/PAzwpoJeUmHF1m+IXZT0VAct37s
aXEO3EGhNlpy2lK9HMn9moxGUudWzF8NmeGJJ1+0xuHsL5+0j6d7k01q9KuFbRtYN49FS5jQ
Xz5pD6PJqcYQtlom56n4uPSKBuGb1OrX9OZo922REMGhYqgrr71deRcQu5+SBOzo+X9gd9dn
icHPN7C7K7SCFrsGdu/+ahIFP9/Abv3+JKdSCRSQObB7+V1O1MDJmYFdkri7OXVPywh9ZudR
c9MWYhhhx4n2VS8xwLC7nvepaJyqVTGm2lXQvB0tUdKLXr/rM3cqGL9V1SJMTSRmRlB6t+Ii
cU/vTr+Ih1sTPWpHrqsIKFBCS+a//bm+afKcisaJmmTNhYo2Dwd8EcSqJfTu2sxjdnOc27Ff
847RJDSn+hZ8/vvsbrsqoBi2vwd0d9Kuo06tA7s9aVcErMYe2O1JOwWPvYHdnrQDxSUO6PaU
XQN7FQb2u1N2p1eEPvOKqKX51uauvVa0BvP9GbupYCL5Zq3EWGbNhjYapL5AyuM+YzcVTSTf
WhEybSwZbOD1RQty1/eU7jSKeLg3Tul8Z5oTEqeqWyndbcZuKprIvTk17VaaREskTOm+PWM3
uTmRepTKOQZ33vm6jYzup+QAUSOdgd2dr7OMChYf2N35OlNQyWNgd+frlMF30sDuztcZgz3K
A7v181lP3FCllgO7Il93aQT2P/5/DQZhz8winNuZ5VayH1RglYwXqaFcytZ+Tkbj7O5VIcsm
Vir4+PiiFYLPja740NdkNJKcoHZS4d6pgCOMseib2Z2dVhEP9yYbUQtPQJECT1N8ez12LpoX
u1Nt4m9Gzoon7Nawu+uE3ezmaOZuRqwkHb4W6T+S38l3aAKCD/ySnt9lMx771fdQZ82B3cs5
NfkvHeScB3Z7jbiBxnYDu3V/K/ufiQ7vHNjdCTtr2MziAd27u7kn7SBlP8FLOOe1eZydRhb2
xFzArxPUc5HqlKk10MhClwzTkPG1ychcNJIa5xqE00g7OKMuSwy9oi59TQSmoilxHyDTwjkr
egEra4rERNd2NnbaWDyKJuxsSmdnNp2to9Pva+aRiW4452Q0ryCsURVmWKBlRVErbGf+6kl7
GE0400jNVDplzeAY0aydzW+nnP8mBT6/zoJ5kwO7l+OV1NCX+MDu5ngd9Y8d2K3729kvhQVU
WD6we/N2mqiCcxQDu3d/taX8mnKERJYP8AqWdzNYaaelhT2xGbCkWrpUatVaA2emfdGKXJyW
m8ziVDSSqIuGkX0Ja10wMe2LlmQWb87eqWhaqqyFWhYuTiVQGb41yat6rehtp6HFo2goNSlZ
zPxa0cnQ4mRbUgVv1z2ns9HkWjTaAEO9TtBoVtzlWS4tGL8mo+EUTsfFRNmagm8BnuxQeLO8
XyDDxwoaaAzs7rJx9/sgWjYO7G56hyZEDujW3aXM4eyMyvAd4K3fX/XrLoMp2oHdvL/hKgL3
BRzgFV2BdnPonlYN9kRAv/iJo1wpO42QAkZUlhxTZJdCE5+T0ag/CmGJ5RRPO0q/Y9EKesfX
bYFz0URtpNQeEtiFGXwd+6IlIiB3F4nTquFRNJGPy12lUM3+ZcHTBGtEBa8FH2ejySS9OO/u
dKj8YfRuidPfHb2bioaTsPVqIWUT48kgvZP3pMcqevcjKnzZL09gEm9g97K8mriCjrwDu5cF
hLIe2Lw4sNt5HqreOrB7C7VhA48Py9oSm7lHcz09NUJbnAZ4San2WmzZTrsGe2al0RpJzdU5
V7hPgEm8Fc3AZHzVgvY5GY0krf7f4jxPckZdOpdovTlxuenZmoqmJydEIaVDqpLBKcu+xq/h
tlR7+jU8ioYiXRwCfE4gW4NnrVeki6MO+VdP2sNoctiUVyd6/uqRhostr+hEvRVbngsnGvyt
cvG7RBWQgb+1lv9/yvAJbIB7YPcyO0liYPVlYDef/AksLtIaS9EHeyuW/I0E9icd2K3fnXA8
T+DnO7BbP5/2lEFBkwO6hNFdvcr9nD0tGuyhbn6tRbPkQswKv8vXDHzc5O0mo3lJRHfrrywk
Kie4YmTUGd21OdpcNJKI6/8Fg5r5rjADueFAf560j2fROJspWkS7OE/1qwlGt2PVknCu7dFm
w6ktEnbV/EIUsnXoxMf3ur19TYZDiVqllil2Hh3GmWtneDO636G/x6AUysDu7rvLBEqhDOzu
wiyjfYEDu3d/JVX08w3sXnKXE+o+dkD3JhRjahLsqhzYJeTuZpr3tGawZ3r5pdXSi/jJ2xpo
m8FLCn9O7q7NDOaiicFcEsqt9kaksL3qig7C2m+KslPRSOrOVLUVp0IdHRiVJcoz99O8pzPD
w73x65c/ZD16IjvoeBSLVuS38g23m4rGWRp1K0rao8gM+hKvmua9HEn6mt4co1Aw7dlqFziX
OlcFe7O7n9XfK4wqtB3Y3fk6NdRW4cBuz9cZ+gM5sLtzdh1Wfjiwu3N2hOpsDOz2nB0q6z2w
S4jdTQ/Uac1gz2wzuDcm5tyJCkgeIkf63Vm7yWiyFb/BqX/duWXQFntD1m4qmkjAsXAwCDos
vX5J1u50ZngUzStrR736DnExBTdnR9ZuMpxaI/+YnRB5TKCFWF4iX3mftZsKh/wVWpt2lSyS
QUP5SPW9md3fZ3Y/pMMnGdTMGNjteTu0FXBgd+ftFO2AHti9+6v+4wS/v4HdnbdrFSRQA7s3
c+ffiYF57YFdQvBu2p9OcwZ75ptRelautXKvuJ35oszdjSbKVDThgdFLaZLZf1HgoUtr2gZv
M3dT0UQSzloLDdHGpWK6G75oScv+Xebu9GZ4uDdZX5PZSmKvYdx9mbs744y5aCIH1yu1VnrL
BTUUXGWccZe5m9wco2hOFb/plQYOZv9TM3ffosNH4GFGSzIBy+Y8tivxVbBad0C3NwGCzdsH
dDfjFAGVswd2694WSmjzygHdy+d61M6xT/eCbv10VVIGt/aAruCadNMCeLpG2DPXCN/VGL2P
vzpo3yNLGpnuR3enotHEGrOHIlaCQKOjuysGbtpdp/1kNFqFaxMhAesmumRA5Uav7s9z9vEs
FoqdCRHB7tdW1EeIluwM57uk9WQ00ll6Ub9DsoDuyLFoyd7c6DxORuOXTGea/kWJbw9KNOee
tN9ONP9N6nuKzr0N7F5mp6l1dLzjwO7mdq2ihm0Hduv+Vg6ZMlRgmVY4tz/hdiV1RbvsDuze
3c0tSQEN5U7wkmzi9clbTueI8kTO3+lNbZpr15K1oJLqq4Y8rsd256KR1Iv/kqJgTIb6gvmi
FWO7r6vSxck7F00UGZh7L9Ybo7fsskT9+sY44s+T9vEsmnBtZcm9mdNVhl095qxe/ys3ep23
no1GuFELH4wsGfaPmZMz+a+uxuu89Vw0/ob361ZYrWujCvbPxqI3x1vD8bZr70kFdbQHdje5
87cpTO4Cu53cGXr6H9i9iTtLWcDPN7B7k2M1+UkAau8d2K2fr8fYC/hOH9gl5O66Q6ucFg3l
oeGE1db8lHKqVcC0iixp0CLT67TKXDSarFEO04lChA4S6BKTM2p8nVaZi8aShbCb70sJ1Wss
zR6LlpC7667Tclo0PIomp87Kor2qlpASBIurK3pUbpWV58KhlD2SaFF5CRLDQ69LJnAueyy+
pqMR4a61eigGtzi9pffWsbsfk94DSdTA7u4HNANL7AO7l+TV5Jc78MdyYLfub4vvBOz3HNjd
/XYdtoU6sHv3VyQxg1/gCV5Spb3uCCynR0N5opzvX576fZ+Ea1YFXQ10Ujn/v3J417K3c9E4
n861ZHWux5Y7OiRRF3QfHJrBV2fvVDQ1lbB865V8ixisnvmiJR2B7XpqvJweDY+iCR30MOZV
1pwF3BtaIn59Q1o/J6Nx+knFornBqkcEalauIq31huZNbk6oIUo0nrLA3ZpznSdvlvfD0nuo
s9fA7mV2nPxnBbbdHdi9J78lv3rjo7yO3bq/kpOh6aeB3fr9ORcqho4aH9i9n8/3DLzlHtAl
ybur17mftac1Q3km/9+tmLXeyYkn2Hvni1ZEo5fy/5+T0USxiP2KVPwaZ2bfW2H6z8psvjlq
J6Ph2plUsrP5Ao8lr7jBMl16vP150j6eRRMzDr2asyDpUhkUA/JVa9rvrgd5Z8NpJKWXEvJG
vj9oOCv6l2/GrL/mwylRk6X2uuIx1tQwO2b9Jna/QIGPU1aw925gd5dnGdUKGtjd5VlGHWYG
di+/iz8T9RQ4sHv5k+8ZXC08sFs/n/b0Eq7HZo4cuoTfXU9XltOUoTxUyucuvTk96USgR7sv
WhHNS93i6tCdjIay1eyBZKd3sJ4grcja1X5z5k5FIylTpyJFnBQZaLPoi9bkuW743enJ8Cia
4AJcS+YcVhPSv5dBPOF3s+GQtp79t6MeDu3ldzdCLXPhUKLSnHhroV4Y7MmmSXOWN737WQk+
BaXaD+jurF00oqBZu8DuztpZAxvUB3Z31q6inhQv6PacXQGN7gZ2e86ugGImA7uC1ZWbCtlp
zFCeieX3yKBEv52WDCqA0JoJBMs3fVBT0ThBKzlrZRY/o+Ck3YoUpLPi64N2MhhuTasRRRoF
1P8IOcUVtOGvH7SPZ9HEK4TC0Y1KqVHx+zVJu8lwYtC8MWdyAgxWL3fk7Gaj8R9/TDNXf+SK
vHN2O0ndD+XsSAqcswvs7pxdBWtIB3R3xs5vQPBARWD3cruaioGfb2B3szt/04Cf78Bu/XwW
DAfrcF/Ehe6ElcvpylCeOWZwiGb7TyNzEdQzepGwst6ct5PRZOf4VWvJraFFJV+0xuD2Jocy
FY2klxlDN78XlEzooMsSg9vbYYrTlOFRNM4D/AVHoR8Smk8os2tLiOods5uNJmtm6516ZlWY
Cy0ZprhsgfyaDIcSi+8KcRXKHdRXp8m0/W9ndvz/XnfvEUkB+cmCV+QCHvxDaoDWDJYDDOxe
FhzGIaAg08Du5sGKWiy+oFt3l7UmYQK/vgHeyzNragry4IHdu79i/lCB18QTvCTPeaPmcVpZ
lEf2Apayv4CFRalVMKBYs4IN841uzFQ0kiwq1z3GZwx1+YlFK9hwvhktnoqmJeaYxmVyqqJg
Z0FbM6VBdNMHexpZPIpGU2+1Bq/v/jc4QeOLlrDhy2rv52Q0Ue0tzuyJqZB1tKt3yU3l1fN+
/6Q9jIZTWKYUf41Wpg7fiecktX87Gf43aQNKBiuxA7uX5VnqhPYnHti9LKAm/yPBM/PAbud5
DA/wDPDWb7CEKBH4AQd26+frnKyCE0YDu4TlXZ1WfvaefhblkcmAOgPVXDo7VWZwzuG1aEnS
86acPRWOMzbuUk1I2dk1TPNWtFw2vjl8p6Lx2wFxDocvloKKc8eiJTTvph329LN4FI0zNmfg
hf2noNLRNqlVAjI3NG8qGkqcM5loWONlsNcgFq2Ipt6UsyejaZrFr0hijFpKxpo3y1vD8var
A4K1zgO6m9xZA4dPB3Z3Cq/6lQjN4QV2L7kr7K8ZcH9P8NZvsPp7ENUtekG3p/BqeZDCC/AS
cndt7lFOA4nySNjfUmn6YnZmFTyiYs2SVsUbdcCpaF5zSLkQGzci0EguFq3gdnRT0J6KpiVy
jmXOVTUqjWgKj5ak8PimV/G0kHgUjaTKtVXq3KN3ApXlXuO8didQNBUNRebbpLfcOqGp7yWZ
b6d2N5eIyWC6ZDbqIlYN1rGe8wN4c7tfpA2YQQWZgd1L8kpqBNbxBnZ3Bs8vqXAGL7CbSZ4T
8wa6Qp3gvRm8gmvIDOzeHc5R/r8ycPlfAAAA///sXUuyJDeOPNHQCJIgiAuU2bx3irFezWK6
FzP3twEyImohWbA9WHh8pe5UyWRaOKVEMjLoxMf9j1t8gkNo3n03mVwuEvLIqaD5K16LUbxs
nxHUbGuLr/g/lWrvhWTWwqlplFIruS9GziiVGBEUXCaJlbVg2L7lUrjn3kULWLLgkK0xmnff
EyCXi8TDrenixseVhEcBx4xryIViqg64Fk1O2qjVoWo3JFZQKDSHyGpObdzWwnEbNyIqI7Pa
fx0VgV4Tx3oTve+VB2zou+TE7iV3JYmgTXgHdu/Rz8kt6dF8iGO37q+2VBW8d57Yrd9fzcmO
AHDU+MDubRIcqaCj0Cc2gti1+8YouRwk5JmDhAobbSisWSuYwLNFIfm7Njlul6KhpFTFZyZb
awo3RmlMC969QOBaNM5qXCfZmF3NuBFdD7GAvR2v+fmk/XgWjcsdug5lN/rQB9jXECR3WGbE
bimanKSoMbrM3I3eDdSrJCgdee8SuBaOneB+fSi5lUYVlFCgxTaAN7H7DeQBfUQSlQc8sLsr
tHmA16UTu7tCWwfaxXBg9/I7dzEFm9tO7F5+55LioCTaC7r107Wa3F8U+3Uc2JC03b2ph1zG
EfJEzd8uFrU1O2xJc89gPZNDDqk5u1uKxolaK6KtSha08y6I3Um9L5qtRVNSby7XRi4B3cC9
8UUh7O6+D0Au34iH0ZQ6upC78vZeYDHriGhKvx/lWYvGFW58NJeMf2dGGwltVUDLasm3KqGf
i+FQyrW0wj6KWAlWgc/v+uyvs7v96oCo6e2J3Z22s9MIdvVw7Pa0HYMlzxO7l9Zxqqg0xYnd
TesKehk+sXvTdppqA23jT2wIsbsjD3bcXt4R8kTPv6fclIcW5Zy1Ymk7WxQzUnHfDLUWjXG0
4Qa2jey07R1O2wUkumiUST12KZqaXErPLfqkCoOnrS0K0ZG59Vz5+aT9eBaNKxaJsQYjq4Lr
HUYIFpUXU5k/aA+DcYbWODe7jnvijvbyulnWbikc1/fNvRO59VxFbUZt0ZvX/Tqv+yaBwEqg
dsaJ3Z21awK2tJ3Y3Vm7NtCq7IHdTe+4g7/jE7uX3rk9AXi9OLF783bsF3fw+nNgQ+jdvdmC
XNYR8kTO/9UQUEd2MREVUMyHQ9TOjN7dkdWPxWhKytmt470FisGcua+JSNvdatZ8Lgfj7WlN
GhMoI1JiqN20InuZRjwMpbDtSGvViN1AO6VDpl2mEoFr0RhLG7m1PkSK/XBAFX1fFRHOuEuo
fi6GQykP13cZoxjzRmcBbdG/IrerXyERCKYBQjIAYZMe26X47JIEnqcHdi/fbMYxULuRA7u9
SoxKBZ7YrftL0pK39YMzKAd46zfYSxpon92J3bvDJMZU0JG3ExzCOSeJnsvZQh6ZjuTUWdm4
TbN/oCMetihi+JXzhA4shVOTBdJyMUqgrOD5WRf1Jv40yjspFi9FI4mMOlOprqPTCSOeEmKi
YsRzMk10OVs83BumSnb578q5D7SxMUIpsdDt3nwsRkPGiCVX1eojHvBQRIlR45vUipeiKXYK
DducStm/K/SKsybv8Lvzzn8rNT4G63Yndi/R60nBaYADupvmaQHTTid26+6W6uPD4E/5wO6t
yrbEAo7JntjNXQEvO3hUoPgAh5C8e4E0uTwu5JHxgF+CemPX4CIuYERtsRXoT5nFuzzpx2I4
NRU7Aon7GDoayMJriEixkbxJymcpmpHUrle2P1RfnVqgXktEf2PJeq/XIpfHxaNoWhJq2kv2
BscGDvL6oi9Nx30sRuOZtSpUymCyhw28HS2m4/5I8vLkOrEUTUmqbWSl0d3/GByjXGy4eJO8
30CMr6BpvBO7m9155h6ld47dze8G45Yajt3L77gn0ozqGR7grd+gkCeXYD0+x+7dYTFaqWBF
4AJHMDyZHLuXb4M89NQgFc5VendpMbSVNUI1dqrItxZOS4Wztmw0byjauemLQloDJxO9a5vj
V2cpzNwFrVv4mpg03kSq5TJueBRNTW7aQK2ruvgj2PVrP+6Q+vGkN3ApGiNrJXNnElKfgUUZ
Xox29CSNtxRN8eYluxex9wcPeLqovRleFMP7Jkk+RQ2ET+xeoifJTjyQpxzYzTQgNQb7K0/s
ZqI3ksvTgkTvAO+t11KqAuaVTuxmKs8Jvr4f2BCaNzl7L98GeWiqIUNaIXfgzQ021ZCImYmZ
d9paOF7c69LUngduFe0wTSGiOuM2ms/FaDRxds14NW4kAk7naFB9c0bzLuOGh3vTq2itI3PN
HbwG15hB5VwnKeOlaLL3iNgNrhcSu1WAj5qtiijXlplG0FI4JdnGsDa/HlFmuFz7ttX49RGQ
7Yp8FdSAOqB7mV21/yXqqHFgN5fw7C0GDha+oFv3ttvLv4EX6BO79dur3vUNlglO7N4CMnlK
EywgH9gQVjfpyL8cG+SZ/0Rrg6RqH92NKMBsV4xT2q3CycdiNMWuH9XCGMqtdEVnRyOURGnU
u0zk52I01a6jzUctu0slojPuMW1eVCbKQJdlw6NoKHV3OCnGUqUPwc4VipJZnjR7LkWTk4iq
/XCKtkxo6Txo9uO+o/BzeXNKtWdN3ZPP3gdgPmJRTOdN6n4DNb6SiMBXyondXqCtoOzIid1d
oK0Emgmf2K37q8UNeDF+cmL37q8mVXQA8MDuzSrWNCo6BXJgI/jdbb/af5ZxWTWMZ1YN3nun
2Uf6VEEPKw6pmNkjf++isRYN2RdtPFWkez4FzD2sWnr+cbD3tl/tczGa6m3DLNXIt1IF74o1
pvuObn19fz5pP55FYy+RYZeIxsP+oJO9FKEc/fqdzp+zh7EYT6NiP0b1c8+4N5a9z0GthJMm
gLVwKDFxdxbMnZui7G7tlfZmd9+rxtcL2ElwYncn7RqDtOTEbk/aNZB2ntjd5XbKYNrpxO5O
29WM9uUc2N1pO/DTvZAhKbt74dtxmTSMJ8r5zUU0+9DBRXJuaJt7hBfiNGW3Fo1n37j13l5j
wGD3oC0KSHJNU3Zr0VR7pDt3IbuQZtSNxxbFULr7lN24PBoeRePZt0as2kQKKUq3vzxltxaN
p+zs3sCZ7UbU0crWhpTd6ua4wHJvlexqx2Cp5J2y+0tL8RVQ5vyAbk/YNVD04MTuTtg1QUfl
D+zehJ3rsYIJxRO7l9mR7Rkss5w3m3t078wCnaFP7Fen6y6LhvHMPqOrnRWqmkVQVyQOMeAi
bvc9dmvRUBqjlVqVjERIQVWWIyST5um6pWhqGsxqN2Y7c7OAD5stihml+KdP2o9n0fgJYVFw
Lll5gLrEJWSQueR+Pyy7Fo3bnDF5RKO4TyycsItpGZxwu6VwKLlkdLfd6S9FPjRhtzRR9btz
uy+R4qMCfqkRboB/ZTE+2NvjwG5vAQTLJgd0e4m4gLm6E7t1d8m2jBkcTDiwezmdppbBGfIT
u/XzSbezHZRoObERnPM2Z2VM4HKPGE80/TWRfTTiXEeTAT4QGqL0Nh3fXYvGJ3GLsU0v3XXJ
4H05aHx34rewGo0YPSvN7lNaFY4mpg6pkxLx5R7xKJqaMmWSLr2pve6wnjlfFELS7vbmYzEa
co/y7Nlr7QPVqHfb25Aa8f0E0Wo03ISyjmzHeEY7m+xQ+FeknP9WKnwVzNqd2L0Mr6UhaJvY
gd3N8ZTQevGB3cvxpCV74eIqIw7ey/JcaBa84Z7YvTtMnGBt/wscUje+18Adl4/EeKTvn1NR
LaVzd6cPMBuXQ5y1iOskubgUTk1q51XTxkKCGov7opDk4l2p9XMxGrsfZPbWe1cCGeDkii2K
KRzfK3uPy0ri4d60nslYXu/U0G5AXxRC9CZdp0vRkNtt2w9Su/2dweFqXxSyN3dl8M/FaEoq
o7emQ3NtaEnHPfneRC+G6G3vGKtoR+CJ3c3wBLU1ekF387sh6NXuwG7O4fXU4dvaCd6bJZPU
FFSqPrFbP59qInB674CGcLtJp9bl1jCeaOiP1I00CJPklgtIp0dM3bjdkqGPxWhc7LDaX67M
Ao8kc0Qsctut+bkYC9tLoRfmzGVQzlh2lUNq4EYe7tW8x+XV8CiakvJorpjT7Sor4B2ixIgS
U727EX0sRkOJcjGeqm4jhQ4kU0j+bpYpXoylZR3kJtBsVwm016ItXSDetO73kd8TVIbixO7u
CuQODhyd2L38zhjHQAeiDuzW/S25pYYaVVzgvfk7thcP2nl3YPfucCN77EGdoAscwvEm1bPL
rGE8MgQg42t2pA8pygRqbr4WReTveFKoXQqnppfqTKmFRq+MFgMjOrZo0CSrshTNMF7ghc3e
dHAHh3JsUUj+btYScLk1PIqmGP98dW5ya00Ii8YWRUzz5hnNW4omJ3XPlt67kN2RQFsiXxWy
OZNp3sXNydmuRUbC2+CMmhgsulu/md73CvA11DLpxO5ldyX1gmoDH9i9Z78LWaDJsQO7t/ou
yU8MLCVwYLd+f9WOW0LlVw/s3s/XkwyQOLygIbxu0ol/WTSMh6YGw0hd5iEyGti6XqNyd5Ni
2VI0JZGdsEYdiO3IBfMQvigie3frG/u5HE1tyi2LUyHUotgNTUOI0ITWXRYNj6LxjrXKvXPn
YfcTuJAZQ+sm87xL0bxMD+0+6TujzLiucgTnrjxJ4K2GM6SyNup1jAw2NORF0v3mdb+BBh8l
HQUWa3Hs7tIsSD5fyN2F2dLB4YATu3Vvu6b+aqDGhhccu5c6tVQ7qG93Yrd+PnYnS4WlWhwb
Qe54krS7jBnGE7V8+2GIW86777ytxI5cWxQxddbGRKxlKRoXAi1SpBrTr7D9X0iWi8asE2op
mpqo2YPTB1Pu8D0nRTjwzMVaLl+GR9G4h+GwS0Sto3FD6389puVuwu2WgnGWNpgH9cZSFOxS
s1Ux3miT0fHFvSnkGo9dqnRUv4sWz9Q3tfteAb5aUdPIA7s7ZSegkNMB3Z6wy+CxcmL3JuxG
IlRE5sTuTtgpg+MyJ3bv5xOXJARZ54GNYHU0keC7nBnGM2cGO5SyHbNZsxZwLNMLnhGV2Nva
5cdiNMWnfkSE7cgtuARfRKsrjVvq8LkcTZVB3FVyrbZBaMouRrTu3gptXMYMj6Lxti6pzahQ
y1UqOK2/2Nb1p2gmMi1L0ThBswd4GMPy5LCgldgYWndbWP5cD0f9V/NqvdVXHyxWWH6XYgN4
3Tdp8FXUwe/E7k7ZyUArsgd2d9qugcflAd3bTVnTeL0lkG7KA7ub3tmrBqZ3jt2btHM3sQLW
sw9sSEX2nt7pZcygT/Ty7aPpKMOO2+6zmNhrvS3Kb/1pUPY+abcWzUtheWS3MmilgN5OGxSW
16JxseQjkNqHgipetiiml+ue3unlzPAoGkrSjN1l5kwiYO2fomTr7i8Sa9EYH8ruDl1KVguK
UBW+ETJSIfeSKKubU0bPQ7gIi4L5YfqLTsru427/84+//+P//vH3//7bf/zX//5t6/kEjsVt
ZkQgGwp4GwfQ7u+QIaxuLoyKCBzYvaTbjUrGA1OTiOG+Z6SbUSG9E7s3q+pGNKjW8YHdvb+l
gSMuJ3bva234XDx2PJ3YgJcJjfvhUr3MM/SZeYZ3V6oYc2ijgTobtigmqzqh3UvReObOLhFZ
CnOvsKVqROaOxq272+diNJyqqF2H3LnXHYnBMeaQrCrdEtWfT9qPp3vTG2sfo7rKIZxVjXBF
LLnfT1KtReMy1pTVM6suMAa+qYLEr8u4z6quhVPScF8oriN3QT1qfdFfkXb/XknVb1QiNOI2
0EnmE7uXBLBPhoLDVgd2L8mTRGC35gHdS/FKKqid84ndTfGkoq+aA7uX4tlRWsF20hMbQfFu
h37t4L08NPSZh0b2ZJfROx/WQEddcogb8W3H/sdiMHbVHL3ZqVstnAEn7yLGKWjc1mY/F6Np
SUd7WYKUllFdOF8UwvAmKfzLQePh3vQqw9u+XdocfTGmiG4sY3j/9El7GI1ztVZ5DHe9VoHr
5iEMr97qgH8uhlNSF3cVrG6WCDs4LPoKvhned0sQ1pZyRis1B3Y3tevoLMSJ3Z2/kwHOg53Y
veROXNganWLWiGmAZxJEAupxHNCtn06rS21gv40TG0Hsbs3R7Ly9jCr0mbWDVzGrESIpOcNq
Li2G2U0KmUvRkAsQinYSIRfbAdlDiAThmLSprUXD9sGaZ9G8mKmgtjSHRDOdc9HLqOLh3kiu
VJqrn0gD72y+6KtL5kvRuL1w72K3Im3G7kCxCldyC8nd3cuYr4VTknTyUry9AwqDqlu+6M3s
gpjdt+TuWhIBsxMndjcFGIw2Ph3Y3bm7RqDI34ndS/CG3abB3OeJ3bu/knoBC9wndi/Jy/ad
gJ/vxIaQvEm32mVSoc9sHXyC0baXmmZG3aBTjegkZL4fRliLxvja6K2SEVf1lsKdJE9uB80/
F6PhVLKxoZ6NFGkDtV180VeTvMuk4uHe9NGNQ/AwWlTB61uM1OWc5C1F43TNHrTcWAa3Dg44
BpG8dmux+LkYTkk9++hl79pyRQes+ltp+pc53mb9wTISbBDzgu499T2NjArUHNi9rI6N6YL2
BSd2L2s3pqECHuIHdjcrZkbbYw/s1s/X7DtB21NObABzKHJv1qWXQ4U+cw4wvuDUQd2ADPTi
sUUxqbu7ZNfHcjRERatPl/aGOrtQkERNneRTlqIpiYVtW1ywb4yC6g9G3B9KHpOi7OVR8XBv
sj1qo3Ojbn9QjZocQYPqrcndx2I02S+Smo1fETX7G53+7SG+cPRPH7XHm9PaaCJl+MQ5bIey
lsF/07rvlx80ytYZlB88sbvLsrmDZc8Tu7ssW+C0wYHd3VFp7ydQ1ezA7uZ3A/XleEG3frqq
Lw8E7Ns7sCE5u8mZexlT6CPXkKSkowi36jp3KB8KkVNkvneGW40m6/AMpAh3Qj2MQzy7jN1N
cnZL0RQ7clVGL3Y11QZ6w5WQovmc3V2+FI/3JqsoF6FeYZvcEHZX2r299Fo0zu6MpnZpXiYl
cDzNV4WkICc5u8XNqVpeztK1aAabnVZ7Vd/s7hsVCI2q+cQZSuscuzttN9BuwBO7PW3XG6xB
6NjdabvawGL2id2ftoNpXYjlyrOknV1uQQGnA/vVtO4yptBnVg5aWpdRXQOloA7VUbRuMiu7
GA1R5UI9c28V1OwLS9rdGbp8Lkbj+TdjDUZRa5cCan5HJe14MpV9+VI83BtPB9FQZZICSttS
iHyQ0bpJ0m4pmvxyoWKporkPsHoUxOqmObvFvWmNjHH3PDoPsAfbF71Z3a+zum/J2WnK6ID3
id2ds2ugv+IB3Z2xa7CO04HdnbFD2wAP6N5vz0v8AjKNA7s7Y6cVdXE4sCH12MmBe9lS6DOz
AJ/za3ZVp2oUDyyAh5ivzjN2i9FkrerGdpwHPMUUkhUyanfvvboWTUmt5FFUbXs6dXRyMaIz
Zk7tLluKp3sjVGsufbi2C1yP/XJqtxSNs7SsnFsZOSv6It2RsVvcHHtB5UG12wZVWKNm7Uj9
3bldhbndE+t67KyImAn/C0vvFbDKckD3ss2aHoh27NbsMAZZH9SH6+76MHsvO/j1ndjdu8sd
l1V07NbPp8U4LlghPrERqcSZ7N5lmKHPzEyoGZkhdx82qoYl32qMYy/zXfLtYzEaslvl6J3H
4OqWGV+aEnkyursUDXvbqFQh5wEMRsNB6arZVMfll/FwbywGLrVJHbmANaAg2T2a3WyWoslJ
mMvQQr0JCWE/nLw47PrHdsb8Tx+1h+GUpE1FO2e3zoG9HdfagH93vvnvJLunBTxkT+xeEtCT
FHBI4cTuJnkKy0sd2L0kz829wKTdid1N8hqq7X1i95I8u9U0sPnnxEaQvHvhvZpP2wz/lyck
L4to7TK6veJRw7oIjU0jl7dyaIvBuPCeO4Aw2VH1oilYaiTEsO5eWnkxGldJLqzuVSe5gQ27
YdLKt40JVzQ/nu5Nr4201CJaFC4XhwxF5H47I74YjXeA2KXIOGseY9jpgnK8iHAm0sqL4ZQ0
WIYXov27Ap2ubNFbniWI420X3oMnFE7sbnKXGzjheWJ3k7sB2xEf2L3kTtJAJ6BP7O79HRns
BTyxe8md4sYeJzakGXBC7uhiEM+MM1prXckInstugfn6mJwX820dbzEaTzUzG7uzYzcT2kqa
esSMh9x6CX4uRsNJs5RhZIgEnnm1RREGvpMM3hXNj6d708egXIwUDUVrL1+vy7IYjYvveWOj
cK5ZSWF2F0O9byvGi+EYUdPm0152N2JChTsWG0fe7O73Ed8baNPYC7qXAkgqil40Duxeiiep
ZdSc6cDupXjDTkOwvf/Ebqd4DOYXT+xuincMbmIUz7EhFO9Weq/mctGIZ8YZtUuWqlRZUSeV
MOm92+HKxWiM4rXafCjZpXwHmsCLuB6Q3JacPxejYeM36lLEXkVvqBJ6jCLxlOKVi0U8dM4Y
rmSjpbsFNiy9FzK9MqN4S9Fk19XSVycAN7tPwEXakB7HWQJvKRxja3bR09Y7ZWPhaP/peBdp
f33gY7v2Xnkgvle+RX2vgbm7A7uX2HEaHVS3ObF7abu9YzJqanxg935/I1FH5VkO7NbP1yhJ
BzXHT2wEsbut/tlxWy/y8MzOQCtLsWOAmr3WYfW9kNzdvRXpcjTUuPYs7s0gHW1aD+klHPWO
pn4uRmOvrVqNYomxulHBPugSVMu812e5ovnxdG/yGH0MuyJ2oY4SuxB9liyTHoClaHLqPvta
2VhqLgIKG+Ugh7d7KaDlzWnD6/9KeozGYF2rb0e0AF73TeJ7gra1vaDbC7MVJZ8HdndhtsLk
7sDu7qq0/yVI7g7sbnKnDGZlT+xecldSLmDl78QGEAg7SO6P3HYRiGc2BlrLYM2DsjDB4nsB
BMLI3eTIXYyGeNTqsv+dBRZ4i2jaoNEm1bKlaIpPDNXhxiKZq6LVMo5IDNHtoMjPJ+3H073J
qnaFYE9AZrCJMEYYsVS6HeJZjMZoGvsMfLffJI1MaGE24jVaiCZZu8XNaT33yrWqzyXDMi3v
trtfZ3f7xfcGKNlwYndn7exqDovvOXZ31k44g20lB3Z31g6cxH8h92fs0G7FA7s9YycE+mUc
2JBS7CSPwhdxeOiXUVorOWepvYHzslHSezNStxgNsSuA9DKKa8PuzNjJrXHv52I0xWXqyd2p
OOcKlmJLzITpRJ/liubH073JQk1bKbWTgPfxIH2WV4/B/El7GI3n3sgIEDejQSMLTOq+PGO3
uDlNeu9ETGPAs8zvjF0Ep/u2jB1O7Ry7PWfX8ElZx+7O2TUBqeeJ3Z2zQ+0RDujeb0/tyEWv
9Qd2d8auEGgRfGIjMnb34ns194tAPNPJH0NENdvVIndFX+sx4nt90v20GA0ZrxtUvTyfwW6N
oIyd3BrVfS5G4xm70jrZqjE62nuSIhon5uXYfvGHh3YZw/64gxi7ljdK7iL67Oq9mfJiNJ57
Y/Gavxa7FIGNI7YqJJ06y9gtbk7rkrv32bWMi++1t/ge/A2jlDnC/uGvLL+Henmc2L2cs7r/
Baze4djtdeKCenkc2K3767J6oLjIAd29u5VwbRbHbv18ajzygQBf+XIBvprl4jVPVPxdS2+4
MlCrpYug47shLI1nkhlL0dgpWEbpRtE8LQKnR1tEzXs627EUDafOWZm0aSkKztlxkGTd7TTE
zyftx9O9cW42spsC2S6htCYmPTpLXS9Fk5MYde5svxwVe9ZQMw+JCGciwLcYjmvpkWdIM1tI
cEPCW4AvjNt9kwCfXQJhAT7H7iUBksCm9BdyN70bHZyFPLF76V1JNEACdWL37m1LpaIO0Ad2
N8HrAn5/JzakDXAyvDsuEvFEyr+6771W6VmFOkzwQjwwJgrLi9E4VxNqQkVKzqAkWpDCsty2
aH4uRsOpaS/sXiH2L7D6HocM787U98bFIZ7tTW/ZWHBt3RhegwleTIl1kr5eisa1ku26ZRc3
zjQa+CaIUljWyV1iKRzjalRFmVVy0QaeqotSQG+C9xuo75GAavov6O5ysdEhuFzs2N3cThTX
3nPsXm4nacDCLAd29/42cP7ygO5ldupsDXv6TmxIL+BkwEMv9vDMO6M1UcpCeYwCnre2KMQ7
o99lID4Wo6HEwtpzluI9Z+gQQcSNlEQmx+1SNJy09lZ1SG65gMM3HDJZPZdl0Ys8PPTOsBvE
KFJLHl1RyZyvV95bisYFVhp5hlhtg9Bh5CBZlimzWwrHSVovxupKaxks6JTFjuA3sft9hPd0
ZLA4e2D3MoDh/r9ww2LeXpyV1NAh4xO7l+GN1CvIQE/s9swsaj1yYndzPBnYqXtAQxjefe6O
LncGemacUXtRrkVYGurA5YtCcnf3xdm1aJys9Ty0UW5dM9reyBGZSLl14PpcjIaTGEvNLKSu
r4wyvIjG5ynDo8uc4eHedLG9qZWaMMHaOV8uvLcWTfYrOWfKJXPnDmo8+qqAcGbCe2vhuIZe
YaeOuRlnhbWV38XZXx/32C68l2FhuwO7uyuLBjgie2L30jp2jUpceK9FDO0/G+HtA7yjndi9
399ITQUe43Xs1s/XyB0N0ClejRhGnMru0WXLQM+MDDw5pER5cC7gLGKY7N6tFelyNNSlyJDB
lRvDQ7wReyOTycq1aIpLu3ErRlFdBAQe4g0pYk7mPOhyZXi4N1ntatiUbXsGbEgcIrs3U2ZZ
i+alzDJ6z0aA7UYOnkNByiyzId7VzWlaJJPtjVIp8JzH2zIjgNZ90xRvL6jl2IHdXbYbFZyj
PLG7y7K14lO8jt3dTlkULMO9oLu5Hbi3L+ReXldSQ5VHT2xIs919jztdbgz0zL/AJSZG925F
Jdi/4MvlWVajsWCY1P3QGsF2qjGCyu0ums/FaEry3icjd0W0K2jcW0Ks3ebM7jJjeLg3xuyK
59W7/0GTqV/P7JaieTE7bWVoL9KowYLKX87sFjenDdsY90FrWRUVq3zrswQwu+2aexW1iTyx
uxN2hVHNvQO7O2EnAlp4ndjdCbtK4Jjnid2fsANvji/o9nQdgzMeJzakDjs5bC8vBnrok2EU
aPRcWCuDjZdhtO5eC201GhLSbotcAwR0pYpK2E1U99aiKS/q0O0umrudt2j/UwxzmKju0WXF
8HBvsjvtuVFGyQ2ukceo7rUJrVuKxmldNXo1eq3V7kTYiyoHzfzOaN3i5rRB3btF+9ABtte/
ad1fWHZPU0abnF7Q3ek6BVMMB3R3so5hc9sDuztZRxmULDyxu5mdNyej1M6xu1N2PEB5mxMb
wu3ummvsxL2sGOiZPv4YTKXZG71phaXQgkT3JifuYjTkfvKl6rBvHPQeDkvZTbjdUjT+2GSj
ENKLEIHtsCVkJmTO7S4nhod7k8W+JM9z0UCn83Zwu6VonKW13EicdZcKT1HEqNNMRPdWN6d1
sSWNySW80R/Ov6boXvkK0T2wb7HuHvUEGUrACzKAB3+TEGBF5X9P7O4cZ0MNu07sdiZccMM4
x27dXyqcqKLlvRO8e4ergn67J3br51PXnQNFs05sSPl6kue8HCzoia2AJJbaOffas6LkXkJs
yeilRXnHUJaisS+aenEtaGMqHc2Sp4hJLxplQlCWouHE3tDSjNwLlY6Vr31RBN2qk3mTy8Di
UTQ1qeZ66E7akwZK39uiCGY/a5RYisbFAN0kxeXzFJ7QiBIDnEwUr4XjE8XMRaS4GuB4jxRv
53ffJQbI4B37xO4lAZwGgRezE7uX5old1UEaemK30zy32oJpnoP37nBLaI7HkVs/25CEWnod
0BCCN0l2Xi4W9MRawD6ZUbtemr3YOziqYWtCBk8mnl5rwRhVyzLEZ1aHcSLYBStia17KkHeH
7lI0dq2iWnqp3LJLCoP8LuJBK1knuc7Lw+JRNNXNp5XZVpERVnDiLcR8utDtrPfHYjTO1Jq4
Iamb8wyCFWMi+F0Zk9H1pXCK0VV/uRSuY3RY7Hlt1u/N734DLcCs4GX+xO4mdm6GjhI7x+7O
3wmh9mcHdi+xq5Lw9vwTvHeHje4qqvd4YPfm7zRltE/xxEbQuzzJqlyGEfRExX+4t52KUlNF
ZdpsTUyb4h2F+FgMhlIvub+sIppWuJQd8ehMBQHXouGXcTMR9epNl9hvgUNaSAvddsL9fNB+
PIvGTonqE9LVncoEzMz7opC+volczFI0LvzSpOU22Oc1QLYaJBczTd8thVOS2huqcav2A8qo
gcJb6jmO3n2TIqCAJOqA7u5VRLP8B3R36q4q2qt4YLczPMloCfkE793fYawIrdAe2L0Mr9vh
g2o+H9iQBN6E4V2OEfRExl/sNS2DWZlEC+h/IUGTKHKnYP2xGI2xNaqNBhU/qWCn0wi98HmF
dikaTlxI1SUb7flBxTtTxJNmFO+ORfx80n48i6Ym7W4/20ulQmC92Rd9NcVbiiankUWatjo6
cwZtcGxVRHp1msFbCqe4nSmzcOPMxODBuuhN8qZ436sISA1Njh3YvQd/8YQX9vFe0L3EjtOo
aIvngd26uyyJQCfMA7qbFnc0rfiCbv10jYzmgnf1ExtC6Sa5lMsqgp7ZeHQyNtJVhnJtoGlP
DAni2zLmx2I0lMiIYrNFQqhPBIV03NW7BOTnYigl9dpa59K6FAIpgy8K4XN33ZA/H7MfT6Mx
gu2KhtRcBBJt6gpJ2RFNtMSXosmpF+nVHc1yVgXlt3PM5kwni5fCeU0W26+/GuceDJ6n78ni
v7YU4ANa17fTOk5ZUTGFA7u7JmtXbLCX7cDuJXY9UQblG07s3u9vpIx6Wp7YveQuG2EDM7In
NoBDzDzayuUSUZ45eBgVItVu/IRrQcldRP7baNh9n/taND4GX7sWtRN9CKP5OgqQ0KNX+eDm
0F2Lptj5+ZLzcfHdDAsCrunv/pFCyP01olwmEQ/3Rnlw79qMDjGq9BmTr6N8P128Fo0ztWx/
lazNQgLfBGH87l57cnVzmkeiUlstBayTrI4ivfndNwsCDlRD+cDuztcpoZ/vwG7P2MHunwd2
L7HzkTqs7HZAt2fsGph2eUG3Z+wYbOQ6sSFtdvelsXJ5RJQnwv01cdaRSevQnMG+Rlv01Rm7
tWheGTt6tdpRVlwyJiRp1+6LsGvReP5tSGlaepWGvuiC/DtmpO6yiHi4N8ou1NiMOnTOaEI1
hNS99NjnT9qTaP4fAAD//+x9y5ItOW7kFw0HJACCNNP6minzMzSz0ELqxcz/m4ATjLvosojr
wWYyb1Wdlqxq4+xOHEYEnXi4j6RdDJZ6QEWLEpy0W1Ihv5GMmd0ciaKCae1VX+0Ef2PJmL+J
HGA20KVgYHcn7QSsJh7Q3Sk7RdUUB3Z7yk5AS+CB3Z2yK6CywAHdnbBjA4dkBnYJt7suk5XT
JaI8ke7nJP7gFc1qTQ20wotFX52wm4omcm9hReCUiDPqF74sYXfd9TQXTUkSOi6UqXXVjDa2
r7jl3HO70yTi4d7ERAiF4E6pBDZHrxEV94/DDbebiiZYmpPu0qxVp90d25xF3I74Km//Ob05
3ISUau5U0L76WPRX5Hb8FXKAYGPRiovZn1h4z98nWJElsHv5JicWUEJ5YLcXiQVNth/Yrfsb
IiuhngorsgR49w7XjDoWHtitf193Hl5AzeaBXdIDeJNRPE0syhNnAYupdspOBbI5v8G4QCxa
wjqvm+3nosnO0yTX3pqz/Maw/dWKT73ZTZl4KhpNHgYXKc5rMjd0cretEKG+m9wtp4fFo2gk
UZYm4bVWnHRi0cSiFdHcCLPMRfMSZqm1+SvDMaSCss4lwixCN2XiqXA4kRWOXoROLYO+cTyp
EP67s86/lfBeRkd3D+xeEhCaJmAHxsDupnkdHbcb2M00ryZCS1EneDfN0wqOFw/sXpqniQjV
Vz6wS2jeTXLx9LMoT0wGLAlXLkStNidIWKre1hAj1Zvk4lQ0OXH3nzqycaVrQ2neCh+i3Pim
mjcVjd+uSDNTqUX8JcQ6NXXJGM7t9G457SweRRODuIWMyV9VRp0XFg3v1usx8blgQl6ZqlBT
7rUTLq+8oqjP9Msn7WE4JfVWJYsRKTdDWxTmtK/fLO83kN+DSy8Du5vekYIWtwO7m9455YXp
XWD30jsOfQ1UV3mAd++wEw6wb+HA7t1h4jBPBAnyAC+pHl/Ls5TTpKE8Uc5vqRCzdHNa5HQC
VuBbUz2+HrKciyYn7c3f99qdC2dQTzA7j1qRx6s3x+5UNJH+NQk14t46OP/qa5YMFNwljE+L
hkfByEuiKLdGjUtvWN5rjWj6rTrLXDRO1Vr1SPw/rRBqarpIgI/69TTvXDgcOVaqVTSGpMDy
BE/mWN8E7/cR4IuPJcrzAruXBVjy2y3IAg7sXhYQ2RF0JPXAbuZ5LamC17UTvJvndUHvkwd2
M88rSWGjhgFeksi7tjcop1lDeeaj0aW2Enah4QaPqvCtcNnVS1/aj8lgnOaJqkajIJhj9RUr
Qrmt1U6FEmVX321/sM0/X2BNZVmt9uY2cfo0PIqGk9Pv5rH43pSKS/AtsT++I3lT0ThdMynF
fF+cfkvBst+x6quzeFPhlPgEdPNjSMLTGU3iTb03b473zQp89YECX/0GBT50rmJg9576/n0V
7IJ6QLfursbXH8zODuzeX6+lImhx+8Bu/fuEk7MGcKb3wK5gdHdCLac/Q3kims9JSy1qzM7o
GOxZ4yX2qlnrjXzGVDQ5Zc0vvTen0YyaEvqiJZm7m7aoqWj8o8W55yzhJNbhuQ9bI8R3c3c4
7Rke7k1vYb+lteRecaGWJazuMqv6MRkNpepsW4VCX5kY1ATyVUuGcsq15uPs5ihb9msnkxLe
0zBn5fmmdb+FEJ+hSbEXdC+3U3/vwbvFC7q7MssVfEVe0L3MLv4nwbr2wO5mdmjh5oDu5nWV
wFn3gV3AHW4F+E5ThvLMxkAk5hG1FD+eKlqLWdNyd2M0PxeNU7TqUWTr2S9KYGUpFq1ouZOb
OtlUNCU0w50LOUmVDna7x5oVzOFunPe0ZHi4Nd0JnQfjfMgYvbEtkmq5bGT4mIzGCVqlXtgD
yq2WjlZk12zO5XTy5/TmaNjmUG6htArqsuZJa5Y3rftm/T1DhxUO7PZsXQUv5AO7O1vnLwrs
mBHY3fk6Q0VaXtD92TpQFvcF3c3puIK5zoH96lzdacxQnjlmaIgql94q5QIO/S3L1d1wuqlo
Iu2mGuVkk9bQRtc1nO42VzcVTdjE+03K6Xb1Y9zQutiSgcxbUnf6Mjzcm+50rigJESnMG5aQ
updv0f2T9jCayNWV7teHXvkl5I2SuiVdg3e5usnN0dLYd93YPBg4Vzf1GXiTut9Afy/SIKBA
6cDu7r8ixvvsA7s7X+d3U/AjdmB3Z+ykgSmagd37+3U/ddEWqQO7m98Z2sI1sF+cs+PTmIEf
mmaURuLMrknv4GVklWlGve57mosmqBrHUEjOYeuFcog1/E6vovmcjKakqtxKtLVrtOyjSbuv
5nd8+jI83JsurWft7N8SdBQzL2nkvE3azUUT6Td/wqjn1qoIOF++IWk3uznOuE1r9VtKjJij
/O4vOUbxJRp8Gax85hVlzz+zCh/qlziwe1knp0a4Rltgt1eJUau7gd26vy9hPUFp8QDv3mEW
VHf8wG79+17KeiBNG9gVecWboUo+vSP4iaB/COqZdfWLo/UGFhF80QpBE63X07tz0YR9VGNt
WSXXAusLL2HRd5Mdc9FE620WyyFkjQ7bbxDh49M54lEwoacXGskmVXIHCwa+aIn0s163AM5F
E0IrNW4DnWojVVie5atF+ObCCT09iSq+UnWSjlo2vkX4ltG7b5neLSmjdHhg93KAOGfQ3OKB
3c3y/NIJs7zAbmZ5Tjw6mFw8wXt3WFJp4Mk2sLtZXkhNoCwvsCtYHl0xCT98TxcJfiLtb0mM
qWehVk0KqrW8Yi4pq15PesxFE4StZfPjl7uwoNXjNVrLl3q+n5PRaDISETYyzTmjIny2QHHG
T/rrSQ8+TSQeRcOpl249O+dqncELnC9aMrdyo7U8F00QtlrMmoUvhoDjyL5qSTGcrptP58IJ
Qb1uXJx/U644zZt61N407zdQ4SsZTPAP7O7acc0Env4Hdju/Q0+XF3QvuwtZPVTv4QTv3l8B
S7MHdO/ukh87htL3AV7B7vLV7d3P3NOtgZ9I6Dcn7rnVmEikLAVV4Mtrcng3qZWpaHJSK9ZU
6yuFB6uzrOCqdwp8c9H4pSp6DhqJahdw9ikWfXUS7zRreBRNSPAV5dYyCVfQpikWreCqN+os
c9EMdZYsyqVZBu95i9RZ7iT45sLh6K6qnZWtlSYwu3vP8a5id98kwdcLSKIGdi8JaIlQpeUX
dC8JsORfAPCMObCbSV5L1cAv0wnen6QF/8CB3UzzIm+IlroHeEmp9ia1cro18DMnja49dN60
+L/AQVhb0pif9bKp7mMyGmdsrUdGMvshbKhYUtIVpNXqTRJvKpoQIlCPRkuJkUuwn3fS3+Cf
aZ7cNKOebg2Poom7TvYlMToR80ZoEm8JL7qjeVPRhGYyx1hvEev+jYRF+FZszp0I31w4h5VG
KK37vxQd+3xbaawYAdmvwkfYbf6A7u7Q8gsm+Pgd2L0Hv6YGy4Ad2K27q/75Bz+tB3Tvr9eS
ors7sFv/PuEkqIjRwK4gdXdzH6dDAz/TzVcmJ4u1OxsiMD+0bK73pl42FU1O2Uirley0TipK
6lZku27neueiible59old5ZIre6c632ZY94/aT+e7o0/YuS0IatzrA5O7K+hqJxvegCmogk1
va6SiWrnVsBHbdncx/Vc7+zmqL8uvYdcC1qSmBQkf1O630OBj8A5shd0d92uKahi8ILursqy
dLCp7cDu5XU1mtDBbu0Du5vZNQUnygd2N7MztOtzYBewh9uJ3tOXgZ85GfjtnJWkR9NYRp0M
ZIlhxo1iy1w0odjC/v/auVs2tCq7RF35JaV+ddxORVNStdZ6LqXWXsED1xct0SO+m+g9bRke
7k13MsTcnK6SgdqpeU26rlzmtz4mowlmV5vmQlRK6YYdkzuY3eTmaPHNyX63YymgONBbseXP
KcPn93i41BnY3Qm7Ar5NB3R3us6PSfDqc2B3p+sM7WYb2O0Ju4L+fgd2e8IOFDE8oF+drjtt
GfihZQa36BaSIpxBFs2TWvl/IHXX4mhz0UTmTRs1f9ctOu5QUreCcN+m66aiicybFaqRS9UM
Z+tW0IY7xww+TRkebk03ao2VxR8zeGuWcDq+5Nsfk9EEp5POIX1NRKIwp/tqx4zZzfGLkPVM
fq1jAtVF344Zf2IVvp6IwJzOwO7O2HW4Fntgd+fsBK4mHtjdOTslMOc0sHt/P3+m0I6vgd1N
7jqBc7wD+9U5u9OdgR86Z3CjYv5t78ZgjWyDc8ZcNJF+a7V5SCySUdeaVc4ZN9JoU9FEzi4X
a9yK/wtsGIxFX52zO90ZHu5Ndy5U/Gdq0iuajl+lwneTs5uK5pWz0yIWaihGoLrLDhW+yc2J
zH347vmXSkCnx7+qCl/506vwPSIqIEdZ8IlcwIa/SRuQGfydBnZ3mjPcr9A8Z2C3c+GewQLa
gd171zFNx4EHTXQc4L07LInRufaB3fr3Nd81BU+NgV2S7LyZKz59LfiR2UBNNRToWmPysxBu
uVgjDmg3JGUunCQm2sgJZKmotmReI4LzGuG64ihT0fh7J5GpE36Ne2J0OBatSHfKLx+1H8+i
acmJvVGY0IZYK/jupBWTWvcTJ1PRxIhwfaVti29RA3v4aU04pd0MN02FE4n17jevbCGuCcrG
zGbWf3c6/PdRB8ypZTBnN7B7WYD6W4bmZA/sXp5niWBrqwO7meeVGMFEed4B3r3DLYPVlYHd
+vdV/00KKBA0sEt43tVx9e8sp7+FPDId0NS1CpUw61DUEUIXTRbb9RDKZDhJMzVt0qVkMrR0
Ope9+ee0J13zvLloOAYdupJ25SxgNLwms5bll4/aj2fRtKTV1O8U/ZX3RKWKVoj73PK8uWjI
vzmhdGgeTxYuaNqzLXjUbnLSn5PhvPpIcy21kLLCyktzPQdvnvcbyANSB7VPBnb38V8Z/PsG
dncizxpalD2wm5sW/EbJKH8a4L073FOoqsJtFXVzWbvZi0pgh9SBXULwruWf5TSSkEe2GJY4
iqZUW6sEyra9Fi0heNdti5Ph+JPqxxQTqxA4WBNrvjiPNxeMJifdFmbI/gEj8NCNRUv43S+f
tB/PoonGYguPj5a1N3BMqC0ZZ/cf77ptcS4aZ2pa1N/HmOCqqBdyrFoRTvvlo/YwHL+C1vgC
lGrlwTz7HPl+87vfSCCwgvXQgd3du9gYJQEHdnceT1CBxYHdS/OceVBFad4Ab/0FowsAFfId
2K1/n1EiATPdA7uE5l0VOP3wPZ0k5JEvRvhXO8HzE8tKbyAxClPpBeFIu67XToaTrPcioqrZ
MjralNoCY4xs7Sa5MhVNWJmRUyLf99YYK9cusj/L8ssn7cezYFryWKjXHDJ0CvZitjWklfiX
D9rDaJywdSffkpms+8UCLdf2FRYs10I/n5PhlETEuZTmd6PewftRebt8LKB53yAQiKoXD+xe
aldeN3Xs7zuwe6mdhmsHSO0O7Nb9DdeJDI5sD+ze368lPwRgkcDA7iWePdUOJiEGdgF3yHI9
LCCniYQ8M5HQnC0SHCG9AgZU11Q01W6yKlPR5JTFOUmtysQMjtTHohW8zq5nQeeiKUnJGVCJ
UF5iv1hOZUn6rly34clpIfEomKgbN+OmVqsQ6GrLq2Zsruef5qKhVIXFGV1uVnLGp45X9Eg6
BfvVk/YwnJzEg+j+2pRitaNKMvKXnEr5m6gEVgGdCwZ2d4HWH0i4QBvY3QVarmje4MBupnfl
wVjvAO8meBU2ED6wuzOLncAdHtgVBO/SDMPP3dM+Qp5o+tdUWIuv8X8wg69UXdLMn7VeTVF/
TEbzIniSW5faSgMdChYRvJfv1dWxOxlNl1Aazq+SM+jPu2hSN8tVc+TPJ+3Hs2g4aXVu4i+q
9Woww9MlhraX0XxMRhNzx6X6h5tKLU3AzoZFujL5MhH5ORmOvwOZrVTyy7xJgeXT3wzvX2d4
27UCuYIlsYHdnblrCr5OA7s7c2fwCN+B3UztxF9LVBlqgLdTOwXzFQO79e8TSiwgdxjYJUXZ
mwP3NJGQJ8r+4Vtd2HqvxNVgA9i6Jnd3VVv6mIwmxP9EhZ3Zce7wAbVEMPAymM/JYKIfKsRQ
apUQtQalUddwodvc3Wkh8SiaSMORxyPB61BFmUW5uzt/j7logqNF010xirIBKF60SlHmLnc3
FU4O61DO0pjEXyD0xZmrN72Z3e+hGIi6VAzs7tydGKhRMbC7c3di6AjSgd1O8MzQ1NgA791h
SsXQJ/DA7s3dhfU4OL89sEuKszcE7/SSkCcC/5E4Jr+sN6niJBTLD8WiJQTvKtv1MRlNTn5M
Ua0lOyvC7QrKiuGKpleZyM/JaKKrqWbrxsJaQVk6X7RmuOKmDeC0kngUjZM1qi0bk6qhhXNe
cpUIWe1fPWkPo3Gu1lumosHyWu8ow7MVXXeFbtLEU+H4LYet+jnE0dwAd6vO3Vp/d4bHX6EZ
CDYaLWnOXjbysV2bDx3oDeRePsJ+5qF6LQd2e7W4oRm7A7v3RmGWqnSwHWCAd+9wa6Cy4cDu
3WEqqWfUOnCAlyQVb5jAaXUhjwwIahQle67snNPQVqC6pCiZtd0UjOfCSRJqu2Ewl50JoB2B
K5ohsl26qnxORlNTaUzZLFeyBvbvxKIlpPMqEffzUfvxLJqWWmfmnLt1JdC0NBYtycPdKLZM
ReP00T+LXIxVSiVQy47WuMQIXYXzORkOpxLWf7mXVjSDn14/W9+jHqvo3Tcp83UCneJf0L0s
oOKl2YHdzfO6gl4fA7ud50kDUxUHdjfL6+hQxcBu/ft6S/5dx/6+gV3C8W4O3tPvQh6ZEESO
sFBVyyXDTZirEot36Z65cJJkpdK5ammKyv9PVsD+kFi8qedNRRN6or0oF+mkBGYmdI3Ab760
Vvn5qP14Fs2rczfycCEwqAwKHq3JxGW9SWFPReNsTWPU2h+zMO8AM/KxagnH++Wj9jAcTmTZ
slQjq2D7aax5U7w1FG+7KJ8w2tF+YHezOxJQCGlgd7O7VsAv2MBu7gvwmz6qKXeC9+6wpaiV
gfzzhd27w/nVGwRu8QAvYXg3x+5p4SCPDCksCnrhm9VIMqiiEYuW9Aa2m3HLuXBSLTWUY2vt
Bpui1jWyfDet+FPB1KRmompiTlFASRBftIbg3cwXnQ4Oj6Jxgke5FcvVP3hm2OUyFn11Em8q
GqdqXSSbsFX/D9gkHKuWELwrzcTPyXA4FCBFS7HOmcGmWp4U03kzvN9Ilo9BHjCw22kAgURq
YPfSAEtCaC3vwG4mepoU1XM9wbt32AxVrDiwm8u14VSN9oAO8BeXa/X0cNBHwvr+txk7obBe
nXiBQzd1Uln/n4meXqfyJsNJ2jXn7r938x8LYxN5CZvIVq+Z3lw09SVH081vqhy+cCDTWzFu
VPLltPLPR+3Hs2haEu01mGtVzWAZoS0ppd8yvblogrMp5dy0EIlfLVAB5hXE9S6VNxcOJ6q5
tNpCj8ZAAeZY9GZ6//IUyHZlPoK9tQ7s3rO/JPPXClbmyytG+J4q86FF2gO7dX9joqN0dHx2
gPf+gs05OWr1cGC3/n2iyQ9d7A0Z2CXc7nr8Q0//Bn0iqh85H2KWEMrrGRwiXZMoylqvc3hz
0eTkfNGPKKnc/R+ot8YSP3S7rDl/TkYTwgTZXu5pXFBDq7LGviGXqy7Jn0/aj2fRsH+Gi1kt
2lppDa0E2orxjzvplrloIi+fLcgd95JRy99l0i3XSby5cOJ600kzca2tVLSFdS6V/6Z2v4U4
nzVQMuAF3VymBSu0u4uzMR4FdzLxdr1l8eszOrs1wLtZXUOHZgd2L6vjGEzA/r6BXcAc7oZ6
9XRr0Cca+v7w+d+WOcYsjcChm1j01axuKppgddwzFaLauICC4r5oSe/dddP7XDQl1U61iDrf
JrReFouWdKvdsLrTreFRNJyq3w2t1/AXI7QgtKRs7qzuWrZlLprgZ9I4eiNzlVdv3z5WR+V6
qHcunJy01J419+K3CFC8KU/a2b1Z3fcK8uX6wEqj7rfSaODw1QHdna4zQ3nTgd1O7Ax1Cj2w
u2kd2v4VyN2JOkE7Kgf2qxN1p1GDPjPRqGy1tyJ+Q8+goFhdYgbglO4mfTIVjbMzI2uktVR2
bodSuhUVZbs0Wv2cjMa/WNYjiWpE+mrmwxJ1S7rt7hJ1p1HDo2gi5xbC112LkBQ4UbfC643s
KrP1MRlNkDNtwlWaWlPwUVukxHebqJsKJ3JupbP6Tah3huW834m6FZTum5T4sqD2qAd2L7PT
aA6ClfgCuztphwqrH9DNzM4pRwUr2Sd4N7fr4D34gO5O2FVUs2Vgvzphd7o06DMHDaFsOVtr
xYqg7E5W9KRpvUmjTEUTuTfyM9eUnReB5t2LEnZ2l7CbiqZEqU8Lx8FbFSxclkWVvsvR359P
2o9n0YSgXqdqqh4S6r4ZWb4lCbur1tSPyWiC3VEl4ey/FAnYk7YqYcfX2jtz4eQkvfVGjaIj
I8MJu7+kIMqXqPBldHR/hZ7Rn1iHT0D/9QO6l3FytNWiAh62QjTsYZFYwM/qwO69T1hLGR1L
OMG791eJYIWWwO7d4aDhDZV5G+AlOcWbwY7TQUIfyfpboty5iB9l2hWeRlrxg2fVG9o5F04S
bkSWSwn/V1iHb4kzb7vJ9ExFU6M9I8ZeexA2sOpd14xC3FkE6ukg8SialhpzmK40lgb20MSa
FaxTr2ZuPiaDoWTRYcpayC9rWeEJ3jUSLTcjRFPhcGIl8ZuNNCMFDdtj0V+Rdf69ZPhAm50X
dC8JsNBXh6c7A7ub5jW0v/wF3U7yGKzcDOze3RUnRWDn0wu6meCx38PBnPYJXkLwrr7sfuqe
BhL6SNW/xly2f91zVCcLnAafSyj8QaLlZp5yLhynRLmHNW+WnkFVk1i0guDdTe5ORVP9alW1
+4lbnOCBBhLLJnev1YD0NJB4FE1LVlioFtVmFRRgaouqxneTu1PRhGSyhSsTvVQSGRbhW2FH
J3RVXvicDIeTx2D+JbDmYYEJeZ406H4zvN9Aha+gNdmB3Xv811QJPI0Gdju5E7CqOLCbewJq
6hUdkhng3TtssEH0gd27w9lZW0bTtAO8guKVm8rxadegj8wn/PLDnKlklYJKW74WLcnh3Ry8
c+EkdXanJLk2BrVvQ9BlBcO77Nn8nAzGH+yw03Ly3Zp2wd7XWLQkhXeVkPz5pP14Fk1LNexa
QgPk5d6CqvB9uTbLVDTO1Rq12iOfVqWDhJXWaGDfWWnMhROuGN3JKpWSTcDaXeJ3W+AqgvdN
InwNHT0f2L0soCV/JHEZmbLCm/yhCB9qSTawm3leFOjQUugA797hw1sT2+HAbuZ54biJKvEM
8FfXak/LBn1kQBFlV2oc83zE4PzHslrtZXXzYzacVHMVFdLq5zBcq13RhpbtUjv6czKa6OMQ
p6yq0rOB9cBYtCSVd0P0TsuGR9G0pEzO83yHujZwLq5Njo0+IXpT0ZCfe+Rs2MycGxW0Q3CF
LVEpd0njqWg4hR+0+WsTsjNgDsUXTX3U3kTvezX4cgPvjAO7u00rC+hjMLB7j/7Q1QM7aF/Q
rbsbY7oqcI3xAO/9/fyLLqhE4IHd+vfJS/kWHOw9sEuI3U0C77Rq0IdWDd2/550bRaUJtWpY
Ikd8O9g7FU2I6fVei9XWraHP94bB3qlowkM5hP2sdRLURiMWreB1d4O9p1PDo2jYbze9OOk2
8Y8x7NSwRoEv33R7TkVzOOMUKqVRNVAqesdc71Q04SRjuXJYtvj1Dp7rfVdoF/C6bxLgq4TO
zR7Y3RW8VkEhyIHdXaNlAUugA7ud4HX4ABzg3QSvg5OmB3QvvXNOruBg7wu6gEDczfXW052h
PnNnkMK9FHN6HLINaBP/kqTdjRDfXDQxottfQ8qtZHR3lskrXyft5qIJnSmtxhqeJgVVp1qT
GHrloe6ftB/PouFULR6xIj1mYOC53hUNa+WyYe1jMprgaaVoL90PvlIrxlU3sLu5cEJemSkr
hcSywI2rc3e8N7v7XiE+FtRe/sDuztoVcLT3gO7O2VlHe5gO7HZSZ2hB9gTvz9qhvnIHdnfW
jgtjWcWB/eKsXT29Geoz34zKmVrrzXkQ+oPXRV139VpGYy6aSMCJUbAHydVg34yvztrNRVPC
Sk9r65lV0AqKr1nSdXc9wlNPZ4ZHwThF6xyGJqSNDGxW4TVy0XcCy3PRvASW2ZwJmd8k1LYK
LN/yuqlwImsnOYx8qTCBA3ezptFvXvdbqPERo2OpB3Z31q4rqhZ4YHdn7QQ1qRzYzQRPEze0
X2yA9/6CPTFKQF/Q3Vm7Cp5RB/Srs3anRUN9Zp8hlP3/ahxWqCDCMjW+G3I3FU3wtDjKqwdE
paCiYmvI3V3WbiqaEvLrWqWIxeUKK/uVNW37d/YZ9XRoeBTNyz6j+DXWiAqBY6aL7DPKjQDP
XDSRf4sBEYpmSMqwJ9qSCZEb94y5aHLyVz8q5l2Locw7Fv0Zyd0+6vZf//jvf/z/f/z3f/7H
//o///f//cfW0wnsZN3MiEAytOBrvIB2f4ccodSQKYNzRoHdnVPlDlbDBnY76WawU3Ng9+5v
S72B78HAbv39aknRNYWxwAO7d3+5pgybdg7wkqzq1ZHrdOg00qjPjDS6H7RZWnYWgR65vmiJ
G3G5kkT5mIyGU8htFC5NMhv4AoZi6YJo2o1K3Fw0LZXmWx4WfOFAg12KYtEKcqe/fNJ+PIsm
J6rCtSmpaAWJdyxaEQ3/8kl7HA1r0R5uLUUZzt/PKfj9c5L410/aw2j8hdZGOaZc1CpYLPJF
U3vz3cT798qqfqMeobxkQGCWF9i9LE9TI3DYemD3sgDzcx01sTuwe/e3p9rA2v7A7mV55J8d
cJR5YPfub+mpow2vB3YFx7uszvrJe9pp1Gd2Gp2oM1NX6hUVqfRFKzje5azsx2Q0nFQ7q4Qk
YUgtghxvhdCBc7xrwZq5aCxpq1rVmX3mzlhy1ZbI79xzvNNN41E0QdcKN2d3NfeGmkAt4nh6
w/Emo2GKXtUsJTe0BhmLVqSK2y+ftIfRRBo/xAyEmjoDRyer5jITb4733YqE5lunoOz7wO4m
dzWj0y4HdncKzzI+7RLYrfurkqyD5H1gt/5+FhpxYAZmYPfur3AqsA/gAC+hd9c6wPW0rajP
zASKNefGpWqL/n1UanZJCo+u6rMfk9GI/2FCNediygWdR1oTTcs3iZWpaFpSCw2hw4kDdHVs
kxXNP9TOb7o0TtuKR9GEnwZnJiGW2jJcbl7iwpHpZrhqMpzeJJM6tesN16lZkfsuZNdOdnPR
5NRrz6H3xVSN0Pxq/1MWz39LfvcdOTwLVxhQXnxgd7dHopowB3R3Bk9Qz8cXdC/F06QohR/Y
vfk78YMKnLwa2M1VWkuZUNu4AV7RHtlu8iqncUV95ibg/51Vw0xAGVQI8jUryprKN5Omk8EY
RSdhe1Ej8OOwRhQlN7oZfZmKxlKzksU6+T9eDntQAm+Fwc6NdN/PB+3Hs2iCq1nplaWHqR8o
phDeHUvCuWmPnAynNSpd4p+5Kai9EKuWULyrm97nZDg5tdqp1C7CWkABnjz5rL0p3jdKEUoJ
LgQ2aB3YvbSuJEOHIgZ279GvCXQ7eyG37m3piTtI2Qd262/HOeGORQd269+nPWUGE3cDu4LU
XfIgP2tPr4r6zHgjBpkrW6RSFOy2jUUrWF27ynR9TEZTEhGphHFurxmVoPdFK1hduWF1U9E4
3SyVfNMl0miEnbS8ykfkWsm8nlYVj6KhVFvNhfx+IzmjU7O0ZqSZ6k2KeDIcE+pRNfed6Rks
zMaqJST1KpzPyXByCg9tiaGkbgpOz8eiN6v711ndt/TdRcUGLH0O7O7SbAa92A7o7sKsgF0/
B3Tr3jIlXAvswO4md1LBi8XA7iV3lkoDv+gDuyRjd+3oUE9/ivrMbaOVEFLrrYizCJjcLVGr
kRtyNxlN+P+G2F2PyhVcW1qTsrsZM52KhpNfWfy/t8TkLDe0g1BWsKF8OQL880n78SyaoGlh
d0eaK/tFApZlXqJXcynw8jEdjhXzN4aaP21GYPmD1lDv6x7Cz8lwcghqWVOu5BGBNnGx6E3u
/mVyt7nbPqbiQFPDgd2dsgsrajRlF9jdKTvr4MznwO5O2+UCMqeB3c3sakUtqA/s9rSdgC1D
A7uE2d0IiJwOFfWZb0ATIdUW04xowS8WLUnb3RRjp6KJDJxUap2rWUd1rDak7aai4WQixYkD
x2wm6sm6JC+UL6nDzwftx7NgnKKZOW0IPaRSGBd3WVG85MvmwY/pcMzfl64ekuZewUdtR9Zu
KhznaKatRLOHx4QPAL+zdguI3Tdl7cBZzxdyd8ZOOqihN7C7c3ZqaK/9gd3N7RpqrPeC7mZ2
hB5mL+jujF1G9RsHdgmvu7ZzsNOcwp45BrxahUK3rwl3MMPsi5bwumsJwulojLp0cT4Ux+6X
tgr9YYzi+rCdi4aTKPVQhquaGbbakCVzBzflWDu9KR5FExTN7w/dir+rSrY3Y6fXdr+z4Vgo
glIh35xqcAJyicvdXcZuLhznaLkUy7VJ0QZmh2PRX5HYMUzsHvWNgy3jC75Fy6Y79gvwCeg1
PbB7CWeI6qGq3Ad2N+FkRk05Duze/Q17NwGvEwd26+9XLfmHHHxPD+ze/ZWcDq93aHr3AK+g
nTd6xHZaZ9hD64yu4idoUa6S0ZzVkgTcy1/3igtMRSMpSxUVyqy1gA+QL1rR03g3vTsXTUtV
OPeWc++EdgG2SYvYB+IsdlpnPIomdFaY2Pxp672Dh8sicZZ8uTcf09FImJpQbiXS8ShNWzFg
WORyFPlzMhp/oaux32qrP2i9oRccek92rKJ33yTAV9GS2MDuZXn+v9nB+cmB3c3yuqIfsgO7
d397qhmVsDiwe1mepo6mZQd27/5yTwZa+A7sAh5xJ8Bnp4OGPXPQ6MU/79UPXz9+wQd2jT+a
H5E3+Z6paDi1nqO8arlIBYXEYtGSZsAbjjcVTUtFhn5OqVxAw4K04ktyz/FOB41H0bw4Xmh5
SeRJd4ssXwu0zEYjOYxNclPVjI67yoq8ItO1PstcMK+LXg9tlsyMml/PXvTeFO930N/LYLvd
wP7b//4fAAAA///sXV125Dav3BEPCAIksQE/2PvfzwVaVB5ujpQSQ9P+Jp1Mfh6KM0ZTLRbx
U7W3ZGwd5XYHdje3a+A96IBu3d1Q1AN77Q7o1s+uxWAEeK8Y2M2tnpw0o8IsA7yE2V33aLXT
oqE9M5xgZ+09PDT83Q761sWiBdHIpcXy52Q0kio5X7Ts8SiBFwNftGTMQ6+tYueisUS9+/Zw
YW7Ov6FofNGaMY8bZndaNDyKJpRZPAzO3blDZXA+b5H23jVR/ZwM56UU3ar/Q+rBgK+CRcnI
G+O6uWjYn5omfnFk3yO0oM8pv7ndKm73Q9p7DF4YD+hegucHu4Eq3y/oXgoQcnpoR+CB3Uvw
NCn6kh3Yvak7SwWd5hnY7RTPrzRgBX6Al/QF3hy8p0NDe+Y3kXtvOWcqVgvokLZMfO/m3J2M
xnqxQlKaNXTQuqzxe+v5et5jLpruVyuLX9mf7wJeF/uqkYJr8b12OjQ8iibIWs/+kOVewpAP
VatbJL53U6GdDMeksT9mYWGnpWNnUfj8fDfHmwrHOV7r5F+dZlF3Rv0z5jyV3hzvZ8X3KupL
NbB7md2Dn49/4OcLSb2Cmv8c2K37+xLVQ8ULD+zWz6/4eYu6Bw/sXu7p7+gKWqMM7ApmdyPA
105zhvZMMb+rOu1UFlICE0ShwbokeXetdTsXjVNo4d5DfK9lAwcSY9GCaJrdTHxMRVNSF+NO
PVe/moJT7Uu0ETlfCtb99aB9PAsmBj66GWfJVriD2a5V+nuXPPVzOpzmW0I5N+JGlVFit2JU
6qbK/DUZTk7C5lsjHJ2rqGxskqnujDex+xX6e4VR39sDu7vtjgrYNjawu0uzaNfiAd26u6Gq
h2YWB3Yvu5PEYF7sgO7mdl3ApPbALsnaXevvtdOWoT2UyveDlvzAzVQKOIiwSn+v33C7qWgi
jVCdAEsLzQkwk8JLSpn55SB9deBORRMGILVkslwz7GG4xgDEyd3N3PhpyvAomqBp3Epv1kia
Hxa/htxNhuNk3uNQ6ircGKNDseq7yd1UOM7TSEqvKsUJONwQKe/K7L8nd9v191pHR2YP7O6s
XdQo0KxdYHdn7VoDvaUGdnfWjgxlxQd2e9YOHdke2L3MLqRhwJ9vYBewh3JpEOvn7WnN0B7a
ZoiY8+JqRAQOzC7S3xO79pifi4ZT1jB7D2nl2kF9WF4zMHubtZuKpqReu/Nfqp0bPsa4xAzt
ZSZ+/6R9PIsm0nZEzQlEpIca2LK/SIDvltlNhuNkuzQ2v0M40QJ59w5mNxVOpO38plXDK7oL
enC903ZLmN0Ppe0aWAk4oNuTdqj87sDuTtopOo8ysLvpXUfp+8Dupne9ot1fB3Y3vcsNdG0b
2CWJu5t0ymnO0B4aZ5Aft7VlP3sr6A7ri1bMIGi/oXdT0XAiJVVuSlIYVehMKyQc7xN3U9FE
4q70l5lqzg3sjo1FS+jdTYr4tGZ4FE0QNafdXLmWzhWs/++gd5PhNKeqlVrc3DwyuHtwjRPx
Db2bCieHaFhulZVyFjAN+acm7r5Fhi+DZZ68pMSzbNRjvxBfBrN2A7uXdvrrtYL2UgO7m3b6
4QfP8QZ27/5aIkL398DupXVOdQXs9RzYvfsrYQYBNgMc2BW0806G73SOaM+cI17uqObXnsOH
HhNnWMI6L1Okn5PBSGLLlaxka5RhFT5eUi6+G/KYiqanGKs06xLDouCNoK8yBLsZJzp9Ix5F
EzOsYj2uBV062Du3SqGFb+43k9FobqalhB+voYQirXjJM9eb+81UNOXVZlFzpp47Gk2ZbLP4
7Zzzv6TC1xqutRzYvRSvJUV/voHdTfG6ovn3A7ub4ilo53BAdxO8AmZSDuh2esfwRXGAF7CI
Ow2+flpI9Cey/pxMoujVe6bmv1ANviW2bTc6y3PRSMq5lCa5FmapmOBELFrB8PRag28ump6k
WOMuEVIFb2O+6Ls1+PppIPEomiBrVEicF+WisPXKIg2+ayOZ2WikvzzOeogvVpSvrtCrZ7Jr
Eb65aJysCSn7JSVaHEHV6Fj0ZnhrGN5+ET4GJykHdnfRWAyd5D2wu6ld1BRgFT5Z8RJ7KMPH
YNFzYLd+fs1S6yA1HtjNPZ+hS4Sqbw3wEnp3LcTXT6uG/kxAn6txLq36/azCCTxe4Xeml5oz
n5PR+KMaU/tFuDvjB40nZEkpL3e+LuXNRWPR49icEfWmCpq32ZIWx1sdvn46NTwK5qXDp5mb
SUzyCux2tkSH73JO6nMyHOedVp17q1QTA1sc86Ry3d/o3c1FYiqakNSrzdlq03gNoO0Wc9ei
N737PTp8RXEhvsDuZXk9vmTg5MKB3csCWop3GazFx7vFljWJgnojA7uX5XEyNZDlHdjtLA+t
Ag7sktbAm6P3tGroz4wnorrYpLy4Edp9tmK8O+ul49PnZDDiP1jlLmzN/0tYlkjWyAre1Wjn
oul+d1HJtZVeuoEWsH3NaEHWa2Ggflo1PIom2JpauNpyGMyCkiCLhPjyPz9qj8Mxk1pqb87t
CTXSiFUrwrkR4psLJ4bhW6lC3V9WAt4nZofh3yTvZ4X4nMbDQnyB3d18l9GRyoHdfPBHtRXV
4H1ht+7vS1xPwVvagd36+RWNrjBQq+XA7q0d58SojcbAriB2N0J8/XRq6M/MAJw8qIpQbmHY
gM58rJiS0Msh2M/JaDixH1C9kRg1uNDMK0qzdxO9c8HEJFMYo/VuVAW8RJQlGom3Qnz99Gl4
FE0Mb0SuS3MI8jFYad6g1TIbTs9dWbpWyx01j/ZVK9rv7kY+5sKJ4dzM1Sldt17xUvN7oncB
sfspIb4Knq8Du7s82+DE3YHdXZ71V/IDJb4VYnLP+J3fPGF+F9i9/E6SodpwA7ub31UDvx8D
uyRxdz1p2U+bhv5EOj/E+FphcY5H2tEa0xotPrvJpkwFwylzCJxYFlYD09K+aEU0nW8Sd1PR
hFCC/67VCVFrFbyLlUWZrhstvn56NDyKJphaDodlJiEiOHH3/fxuMpxOWokLZ4rxJHSkd8Uw
/D2/mwonFFv8PeA7w/HQgeeWL3rzu3/N77Zr8flhDmvxBXZ34o7RxNjA7k7ctUZg1/2B3Z64
QzWWB3Z74g512H5Bd9O6wqD/yMAu4A7lsq7kp+3p0dCf+mf0mjn82a2Dp9Mi/wy1m8N2KppI
wfkFJGsrKmRw3m7F3tzm7aaiKan3HjItLEUr2KXmi5aU/G6U+Ppp0fAomsjbOa/rqlIJVU/f
oNQyG03Pktm4Z4vBZqz2v4PWTYUTDK1y8dunckO1Mt5pu/9tIT7Bjq8DujtpZx0sGg/s7qSd
isFJu8BuT9qBsgQHdHfKTqzB9hmB3c3tOoNplIFdkrK74XanR0N/6J9BnYm6H7elFow/LJPh
u/bPmIsmWobEnwWN9ifUiXTWu/NJzm4qGn+nFm091NGyGCiNVta43uZ61bP/15P28SyaoGnO
hpTCxZcq2E6zg9xNhuM7Uyu1XmqIifwWkeW5aJym5SJOU602Rj0fY9GfyO34O1T40D7m3ZVF
kJ8seEEu4ME/pgyIvXsP6O4MZxjeoBnOwG4vXcMewQd26+6aJGWwE21g9/JMTkLgu2Ng9+6v
P/NWwdHsE7zgZcL1pjnx9LToT3wGNDWlkFqR2iqDJUVdMu+Z9UawbS6aEl0qkv1WGTMt4NhJ
WWLdmvvloMbXZDQ9mWSPwpxuGYPq7H2JqM/NYMNfT9rHs2hC9zvMRtToNayxUSyc6XIi/3My
mpyKVjLKIUpNjN4gV9gisNBVC8vXZDQl5fBZNw69Q1S2sUyOa/12IvxfkgYU2FPuwO5leRpz
dyDLO7B7WUALRU2QBBzY3SzPUE+Zgd1eKX5QKF5RJ36yu8WSNLC/8wSv4Hh0c/Kexhb9idmA
Jg01XhGuxRiU0/NFSyrZcqPpMRVNSdpb49JyKdnAk9cXrRktvkqofU1G01OuIdhWpWqrYO42
Fi3Jdt7cJk5bi0fROF2TwmqlS4hzYz0TPClA9zepwxuONxWNv3NytBk0adEJgpZ+V9xFudCN
OOBUNCURkW9NayUzujex6M3x1nC8/eKATWHZjsDuJncVtaYY2N0pvBg7Q1N4gd26v5lKMkXH
YwZ46yfYXoOv4BN4YDe3oVpC+3le0BWlbL1pHjv9I/oTVf+amFvvUpSKgY0XvmbJ9MmNtcdc
MJJCWbhFhiPE7TA2FIuWVLJvpDymorGkzropU/YDF4vFl6zJd910TJzmEY9iiTY4f8hIoiVW
O5rvmmuDe6IZMxUNJeutiFQOYcAK9qIv0oyRO2o3FQ6nbESs4cOoVlHa/U7fLaN2PyQMKAQK
BA3s7lbFXlD9mAO7O30nBez0HNjNDE+SKOouN8B7E3iSLKP2bQd2M8MrqYK6EQO7IoEn1/LP
djpI2BNdf/WDJxerzJkPEwQogbfitMp6aUb3ORlNSY2LFj+ynPI3hRv8Voyi3GkDzkXTU485
FAu7M7aCve76d087/PWkfTyL5jXEaqqtV98ifNphScpLr2neXDSU4mJUekwYl1rBtvlY9a0V
9K/JcELlj6twLr0KKiz2VgZcwPJ+QBkQNVYY2L3Mzv9MAi9NA7v53Hc2CQ5svqB7d7ckP/pg
XaDAbv30Sk6tgs2VA7uXdYZRB0iLB3ZF5k6uy7J2GkfYMzn/1gqXsMAIjwL0fb7EBkP7tWfb
bDREVXN3TmL+u6MDxks8hlu/zqjMReNfOyshpWfirwdYOGZJfohuFCjtNI54FE1OFK4xuXeP
CuyK9DUrcndFry3b5oKhmLmszrmJ2Q++jk7ULBkQunag+5reG2nNXvbc3Qr42p11oHuzul8i
C4iqxxzY3YXZDJO7A7u7MCsZJHcv6N7dlfgjQXJ3YHeTOz+dwQnjA7uX3PntW8Cq9sAuSdnd
kLvTMsKeyfi3aAzPRUKrDTtyfc2SAWO7brmbCyYnYxHW5hFVtGM4Fq3I2NFVNvVrMpriW9PI
nKlyFJvh/OOajN0Ntzv9Ih7uDbFkE6s5FA6xaGLRimgupXA+J6OhcLEsrXJzUk9aUPGYtoKr
3g0Yz26O+G9KxKUbKa75/O65+/fkbr8mIDov+4LuTtj1jioCHtjtCTsCR8IGdjdnb2ihc2C3
p+waOEoxsNtTdh2Uoh7Y707ZnX4R9sz8ws9YZeq591JBbZIdKbvJaJyZtmbW/ehzDvFrUnZT
0UgoXeamVZpEIhLsHZzrb39C6063iEfROEPLUYM1J0KKis0uo3U3Jf+paCL7Ruy0WzV2HrR8
3pGzm9wcf8aUaiVtrYDemLHoTev+Pa37KU1AUB7ogO7O2AkqhvKC7s7XqYI3nxd0d76uVHBM
ZmB3M7ssYB/OwG79+dScEoE/38CuYHZ2c96eThH2zPeiNuvNst/TG6rswktk2rLeqFPMRZP9
Cpe5MGvNWUHlkLyk7yn3y4rf12Q00ZhJlDUGKVrrqKpL/faE3ekT8XBvKEtl7i3uEGCGKy9h
3Vwux48+J6NxjpaZxYjCdQ58z9OqZOpNanhyb0qtfiPyeKQWsJnTF/2RxK58hyBgBZMAK+7/
y8Y7Nnf/aTKYkhzYvXSzvObiYfG9vOJYeUY4S0bPvAO7dX9DaqWAsjEDuzdZ1/zejYo8H9jN
yWJNpYDGhSd4RZG4Xs0OOBU4bSzsibeAph6WwGK5BSPAItIlBqdZ+SadOBWNJKdoWfwT75ka
2H8bi1aQzrtm+6loLKn/rrV6OMyv/gBsfHdFAu5OfM9OF4tH0XCiqiH+83rYUE2tRAsS1zf5
t8/JaCKVVmKyo4ZNIXgUzebf/ja9ezNBNBWNH5HOOLN2ziEChAoazV2kfzvp/E+J7yn4yh/Y
vSwvNE3ARqyB3c3y7AHLs+0sz3lHBfU4BnYvy6uJwDP6gG7meOwXG1RBe4BXcLxLSWI/eU87
C3viMaCplqq1dephUodyvCUXYKWbdM9UNDGOxI00fgkYTKxZkle8OXingrFEEkS1CBOh7R22
Rq3uTnvPTjOLR9GEVHIhf41QoyBGe/WVb0Z3p6KJmeK4o7RexAo4TrRoEFkuvzZfk9GUxFZi
PirKxgQ20MaiN8VbQ/G2a+9VA7ndwO4uGFtHa1wHdje3awqeLgO7dX9DbKWiKdATvPUTbC0V
BrVtBnbzDjunVDDJfYJXFI5v9PfsNGmwJ9L5NbGoaKbmZ3oG3U590Yqsl1yWwT8no4lHtVIx
kWZMoHSOL1oy6XEp4Ps1GY35ta+QH7lFtRn4tMWiFQQv3xC806ThUTShpuebwupfhcLgjJkv
WiOufJWR/JyOhmpp7F8bK5xBGbNYtCS/ekPwpqLhFOqItZQu/iol1IJxzpz1TfB+kQJfAb+I
A7uX57XEqAb0wO5lAc48wPm7A7qZ5an/maAMzwnem8OzJATu78BuZnkS3nYgyXthl9Rpr+pN
fvKeJg32RDq/vs6qrlKLH72gP3Ndclbl1wzk1ck7FU3IlAiZVj+wKiz0s0ZNsOcbjjcVjT/W
lc3ptwj1Bk4WxKJvTXv99aR9PIsmOJ4YNf+gRAvMipbILFP0u90/aQ+joWR+M4qUV25SCCxt
+qoVOcnM1y5pc+E4X3v555DUlgV0DfdFUy/dN8n7WQE+RS0KB3YvseNUCzjiNrCby3epF1BD
ZmD37q8kUrCDbGC3fn7ldUZjB/MLurt0zIzSzgO7InV3N817+jPYM9n81tmEc47LO2g3HItW
0Dq7OWwno8kSxUw/nWJoFDYBWJGIbHajnDEVjaTcfUuqEwe2AiciV7znbpJdfz1pH8+iCTG9
SKkW9X86OGm9SIHv5aN9/6Q9jIZSmMSS9bBoqbVjXxxaYrPMdNfpObk5qhqGM8bFn2R0c+aE
sd607rco8MFqHoHdXp6taOvdgd1dnoU/v4Hdze7UUPnsA7uX3UkqGaQbA7uX32koE4NZrgP7
vfxOaFgzxP884ncsLboDWiYmWK1lyXjFdWl2OhqyGqPJzoi4gS6+zu9W9N7dqLVMRuOXqjDv
zRapFOzIlUXqJtcTvWcsH89iCdmVzpVVi1UC6dD3s7vJaILdZa5d/GZUGTfNaEu0ry/7b7+m
N0dzbUqWi98o0GrO5BzPm939rAQf7Dc2sLuTdqjb0QHdnbJrHSxtDexu0t4VJXUHdjepI/Dj
O6C7U3algB2fA/vdlC6ftOGpZ0bT8IY1ZgMz9KtSdnSpqzwdTdYewmjW/HQyOGW3Ym9uUnaT
0Uhi53RSfF+ccIO8IRZ9N6nLJ2946plRWm0UHr4VdRNaRVFvSN1UNEHPVKtaK8LZQA2d70/Z
TW+O70oLb5amig8Az2mLvUndrxDgqwZqZgzsXm4X3T5go90LujthpxUsFw/s9oQdrsG3ZBLg
WTG2VzRdd2B3c7tsqLjygV3RZXfpC+snLp/84ZllRjXKtSq3Zgw6GcSiJem6S42K6WhIpGq1
kHhBs9G8ZLj0Pl03FU00GdRaqBOZofTh+8WVz2g+nkUTanpW2Z+14g8aboj27dxuKhrndi3s
P7rVIt3AWjktUSW/T9hNbo5mcbbqlwnRBr53Y9GfyO2+RYMPvZvlufGUP0eFD9WwekH38k3n
GQSqwg/sbsbJCqqfDOzW3TXxzwR7tRzQvYzOUi9gHWlgN+eKo+qLVSAHdgnjvJzdFSonq3mi
4//qPFWWVkLmDWScsWhJNvHSZGEyGklsmq1ZLl0a+PhIKmvEWW5SPFPRWFL/2jkRaFWbgV1Z
sWgBqbnR3zuj+XgWTejvFfOrV69VssDiLEumVC4p2udkNFEeJSnVL2m1VFgmeYk24o3+3mQ0
JZUoeKuWbqWB9DkW/YmE87+kv1cFTNkN7F6G11Il1BT+wO5meB3VZ3tB9/I79ZMA1Vg+sLsZ
HtxCObDbGV6u4NfjBK/geHKpsSwkJ494IumvyX+yxuHuUVmxgzfWrKB4fEPxpoKRlDM1Ja7R
di+g36QvWkHxLl3BviajsZRN1aiLddge0NYUjG/0985oPp5FE7nbEPJ29vjKku7V37tJX09F
k5P0RsVJXnRpoiINSVY0AQpdzUZ9TUbjbI2rOL/LVJ3qwRLLUxe9N8X7Bfp7MZeE6u8Fdne1
WMHX3QHdzewaLqzcNusqh5yeZpSZDPDWz69Z6qg818Bu3t8WugzoDh/gFd2Ad/k7PQnEE+X8
mC12CiFmfjtD/TNi0Qpy1y91WSajkRCytEYvtqpg4SsWLSF3N92AU9FYMmtW/ZwuoYoG1lhp
Tcn4RnzvDOfjWTiho0fcujQRLbjlxBKt6GthluloMlFoXmvcLFHj9SWzRDE3/E+P2sNoOJXs
RDX7tggV8I4Xi97sbhG7+yHxvdJAFjWwe0le9+8LeCYN7F4a0JIUBUu0B3Yz0VO/taHFhQHe
S/RKItSHbGC3Ez1Fpz5O8JIk3qWJhlA9ycQT/fz6cmoIxQnO1MGHtq5pplO69DaYjCZkSrpl
f1yJq4FPuC9aIsB3V6idisZSpW4WpMi5EVhEt1XuvJcCfGc0H8+iCS09lV6cR1QWcJpwFc/7
5yftYTTkJFylhN9w8f9huNNxCQm/VlmeDCcEk4uHY9WjKYyadL9VlheMfWwX4GtK4LzHgd3d
f5czWF8c2M31u9RRiZGB3bu/IaoHjssO7NbPr4i/OcGTeWD31o9rEnCg54CuyN/dTfO2kzo8
U81vvUa5TMRYwBwRL1GayGo3xdnJaKJxjEvxeGo12ANgRXH2dpp3KpoYzKUcUwVEtSrq5rtm
mvdagO+M5uNZNKG24i8Rro0KKz7x8e0SLVPRkL+wu0rTpiYk4OgcLTGOvp/mndwc1ejArZxb
NdA84z3N+z8twCdoamxgd9dnO0g+D+ju+qxQgQu0gd3N7SramvSCbmd2GUzaDexuZqcgdzig
383s+skenknlN3+ZSyvmfzHYirFMeu8mjTIZjZNUlVDF4d5RQ52UV8yJ9HqTRZmKJq5T1sKO
lFVgHdRFswh3s7z9JA/PHDOIe+1O7koztKlhA7GbCoZek3rNzKlqaRk08d0h0zK5N3p0ELIq
l4xq6Oi77e7fE7vNZ35JlEHH1oHdna9jAfNNA7s7X9cqSDkHdvf+9gq+XQd2L6vTFGkKjNUd
2O35OgNp0MB+N6+zkzs8tcwoHKomXIlBI4Nllhk3x+1kNMz+IVWJ5JCCblu8pn/wZTRwddpO
RSPJN8R/X2lOiBgcz5Yl0dzzOju5w0PLjGzduYPTbjWwrLxDo2UqmsjYlW5ifnswzmCPWqz6
bmI3uTl+c6AiypmF0Gbxd8ZuCbH7oYxdE1RS4MDuztiZgPqpL+jujJ0yqgt/YHdn7LTjdmiB
3Z2zU9RneWB3s7vKcM7OoQv4Q6HraYp8WjLkZwYT1Zr24ld1yxV2y1ghH/LSXrk4cGeDoVBz
8BOqqGTw5hIWGyuo3Y383lw0EuVLc/5QSUoDnUdlVZbrmtrl05LhUTQvapdVqZVOvaH1vm+n
dnPRkN9uQjfE/ArhfBU03tvglzG7OcpsTr2JMnfQHfpP9cvg/3n5vUcsBSQoC16RC4jwj4gC
vrSbwTTYgd2d5hS0cP2Cbi9cK/i2f0G37i1LS34ogZ/eAO+lmQUfiBnYvftbupNbdDR7gBe8
TPhyeNUZymllkR/5C6izDSLLWVtDVZhei1aQ4Utm/zkZTkndL+St5WySq2JZ2/DQWVK/vnJN
+ZqMpidh0VajqbpncLwpFi3gW6+e7/tH7eNZNJpKDeU5vxWSGOgB44uWiDeX6x7YuWiy/2Di
T1huvkHW0D7LJdEUurl2TUVTkr8DSuv+L6kdVAOO6uafyIX/U8qAHfWRO7B7SZ763ZHAjMaB
3UsDWiL0Uv+CbqZ5mjLYijKwu0menwMwyQvs1p/PIv8LktCBXUHx+IpF+Ll7OlrkRzYDkooq
dVJu1FHS6ouWKANe5tQ+J8MJzyMW87OqdKqgMGdZY57yelleHbxT0WjSYmy51FyLdZQUrTAG
4lfq+/5R+3gajXO7qpnJ/FYBquLHoiUU71r8eS4aZ2seDRVmzb41YNLIF63Ym8toviajYb+z
1UxCWp3jwS0gc5n1N8X7BcqAvaGSHQd2N7erhHO7wO5O4VW0AX5g97K7mhMTOm8wwFs/wRZu
LODtYmA3J/Fqkga2Up7gJfXsG4Z3OkjkRy4F/v1Q6TmbEwlG7Q9j0ZJmxZuK9lQ4koRLblHP
5gaOf8mSrFd+0eOrY3cqmJ6iUZE8mNy0gi9kX7TE3UNucning8SjaIpfc4S1dJEoA4ONKmu8
Sq7L85+T0UR53u9Exiz+/gb9MPJk1uv/R9NuCN5kND3sqHsxQq3xYsmb3i2idz8kDSgG3rMG
dne3YmdwWmZgd2fwBL3YvaB7OZ72VCqqrDjAe3N4PTEqDDiwe/eXJPUu4A4P8BKOd8Uj/OQ9
LSTyI5sC/9lyC905C9dqcMJQlihh3Bdqp8IpyamqcmlSrKEi7LFoRdfipSPG12Q01TmBComf
vKUzaBpc1/T55cuc5F+P2sfTvXEu5H/nmDcuoPBsWWN6RjcK0HPRUDLuIdnIaqxUsM3xVWta
Sq/ViubCyX7RadGwwTVsA2F57nca71/zvP3KgJXQFrwDu5fbhRohWF58Qfee/OFe2sH83YHd
ursmcWbAxryB3fr5FY6CMHguH9itP59aUgOLmQO7hNfdjAic7hH5iaR/OGqrRWmmCoMNa75m
id7zpT/B52QwUWNqajk36qxg7Xy2xvS32uy1XepcNCW1yk5OqXanDmCLVyxawupuarOnd8TD
vWGqNTq8Wom2tY2ijZz1JnU3FQ3FgdIqZb8+UIzpo7Moa0rNN6xuKpycivWeQytduBBoOJ5k
aiTtzep+hTBgIVA67gXdXZzNYOXugO4uzQoqsfSC7iV2JRHK617Q3bSOO9h0N7Bbf76QwEYd
2wZ2RdPdjRlvPr0i8hMB/zDWNaFeTJvfLdC+rrrge+687tqwbS6anKy2QiEfI5XAiWlftCKa
fpetm4rG78rdKRBzE18IZq9j0QomRFeDCH89aR9Po8nin5E/Z0RSBfUEy0uI0OU80udkNM7Q
RNVKTCT1mkEpiWW87h8ftYfhRLG4kW+OtaboyN3sAPib1/2kLiAnZ/Cwj0dgd2fr/DACOd2B
3Z2vaxWsNQzs7nxdQ/d3YHcTu1ZBf8uB3VsppsQiYKX4wC4hdtcGbfl0i8hPJPyj1Bc5hy6U
tYBJobqkZyjrpdnr52Q0nKh1MxLRUCoFs/lpRS9ubu1a73kumpI6M9dsPXcqFeuBKmvMIm4T
dqdZxMO9YRJ/0ir71jSwqMyLfEnuxGOmoqFIprL4sRI1fwZFpGhNNvU2YTcVTuTe/D1gIv4F
yobeiN4JuxXE7qd0ATM4rzCwu1N2glZjX9DdKTvN6Ojhgd3N7io64TWwe9ldSdnANraB3Zu2
09QNzHoO7Ap2d5ka8jP3dIzIT3T8/WJRuJEfvLlSA5PMsWgFu+s37G4qGg5Vh2a1sJMhWC5p
DVdtl6mhr+loWuutapFeOprmWnHLcW53M0dx+kU8jCXXmoMJkdYKvnh80RotlBtuNxVNpN9M
sv9tpRYV7D2/itvd+DzPhZNDa8BaMX+NdoOLsfRHaj6X7xAGBJnAkpadZQMe+wX4wPa1A7qX
bZZU0DLdwO7mmwXtnRzYrbvLYqkqSJhO8N58XfeHCjQeH9jNO+y0C/UuPMFLOgBvuMDpZpEf
WQxoKtn5EpmWzqAj3mvRCtLJN6RzKhxJMeiaq1llRjMjsmTgNfdL0bqv2c0hZ2rBbnrujQqY
56E1TC3Xm+z1aWfxKBy/+ecWOTguQqiPgK5RFKRytTmfk9HkJK0V7S3m3gi8E/ii752t/pqM
pqQwK4wyPnFF51RKqu+U4iqC90MafLDM/Qu6l+f5Hwl7ChzY3TzPHviN2G6/kaBuUsEL8Qne
y/Nq0ldGAOF5B3ZzX0D4ToONCyd4Cc+7rufxaW3Bj/wGxL++tWZ/wTufQCf3fNGSWY+bucq5
cEp8m1SUa6tqHZ7gXWMVfD3rMReNJa6FSVsTa0YYMYpFS2jetXkhn9YWj6Lxy0Hp0a8Z4XRw
b3zRClXB61rr52Q0+aUHRLXl5owYNFzPa0ir0LVMy1w0JdQ4tfl9vlOwVvB7M1dwetO8X6DD
VwmW4asrJAGeVY0NraW8oLvZXVNwBnVg97K7qqnDgzIDvPUTbC31An6CA7t3h1tPnMG2xRO8
hN1dZ1b49Grgh0YavWqzVjM5A8UHz1fMSIhdZ/HmwpFURZsQNTIyxpIRskZRsF+mvb5mN4dS
DYs8f0GEpzM4O+aLlsgs87VpC59uDY/CKcmvEczVahFBu35i0beWWz8no8mJWkySlKYto9bh
sWhFNO164mMuGk6i0mKGl0pXMIsXi970bhG9+yEdvixgFmVg9/K8lvyJBNtMDuxmHvAagEeF
+AK7nelpQeu1A7yX6VFiRZUgD+zmHc6poonGE7yE6d0kV07LBn5kC6Ap1FqschjvwkRvRaoo
vw6Uq9N3Kprwzg1vMY2OR1K0XEsrkpL9MvH1NRmNOQlnK8XP9S4C1lVi0Qqep9ejvXxaNjyK
xilboSKNRFk6OJ0TixZEc+26/TkZDSWr/oD5i8f/QxnUOopVC8LhuzzeVDicitRoQSbWwmCK
hyfdQd5E76eF+MAK1MDuJXf+Z6JGSAO7uYSXUEvBA7p1d00TgfJRB3TrZ1f8qGVUHvfA7i0f
WyoZFYA+sAuIw91YL582DfxEPL8mIpEuhcQKg1+mWLSC1OVrc9K5aEITxNiimlkFHx1doQkS
bXLXJ+1UNJJKax6Mb07tDBou+qI1ox/XZi182jQ83BuOdk8pksOxBZ3qXaNGfMPppoKh1KxX
0VKddGdw4ppSXzGjnMu13/JcNDl8upvfhnrphGci5/j2m9L9DhU+dPpqYHe33xHYi3JAd5dn
hVC3qQO7m9kxKokysLu5XVZwxGJgt7cGwtzuwK7gdjeupHy6M/ATyXy/U1APt3Yj7Si3i2L9
dDT/BwAA///sfV2O5DiT5IlGIP2HTl6gHjJPMcC87i6w938Y95BUGHwDqUz8mJ5V1dGFbvSD
qTssqJCMTnez/znUe52ONscm3FeIxIq5YGVBBcQSy5beri1b5tj4lkVVqPjqaGFwIMEv+mqP
ZTrDGR6uTR1tRDlIxiBCh5S/3LJljo2Lu27aXXPzMKqg11FIwhV06KY2PEWnbso8qnXpvjtC
rca2OaeMt7r7Zi++ihfsAptdsDNGE5h3bHbBzgZcsLMVLd0PZR06mXpgs2UdNVAWH9jskp1W
8KT4wH51ye6MZ6Annvm+4WH21xLF89wG9rJta8Im2qWN78ckm3AEGUJDhhQbYCrxGkeQ+5Ld
FBuJ3d4gGaHp0JNLmbRHeyLrznSGh2tD5JtrbTEGDJ6zbCuSGO9F3RSXV8XOn4kc5sou7LCl
ySjZTdGpW6vDrBbfNwp4n0WZ763p/n1N900Vu9ZB+5gDm16xA886d2h2xU4FjOM9sNnSrqMD
Hwc2V9pFcw0airZjc6WdbkyotNuxX12xOxMa6Fl6hvmrNlwg2VURWMLVJYUHl3Y384tTbCLg
zP9yZafiEgKu2K0QqnYn7abY8OYUNGyjVbh11GR5rAhouJV2Z0DDw7Xxzb/LEr/ThPCKXV1S
4roTd1NswlJv9BE50WUM9EXkV63xFbx2RJmjUze/04TqqI0KevBfN/0rHVG+xIivojYEtOL4
YNmMR3L/X0y+gl/Ugc3VnOw/YHRfumOzVSeBh+w7NHV1SYvv1cGX8o7NLteNAX59BzZ3da1s
DbWqPMELHiZ82TXnWuCMj6BHnv7hjlZHV6vF0Fyw10UrDorvKopTdCRsBUslbdKsghZTa1wF
u12bP0+uTfHXei8cRja9ga4ZcdGS+NpLEf3zVvvxjI7fNFJtaCMbXMBp8bhoycnqdezzHBuX
XBQuNlX78P869iyNi5ZsCW42OFNsXuEN1FTNtDEaqeQX/Y2q85/kw6foa/bA5oo829TA7ekL
mi3xOvjpdug3SLwHCi/9PNbQiYMdm7y2bWP0RPIErxB45cqyzt+6Z4IEPTL2l61z5WbCGlFU
qANfXxLvceO0PEdHInm7REejKqPt6nHRkk7Am/asKTav0d3um9M4yBugb/Sq0d1L3+ift9qP
Z2x0YwsRIfIa84Ad+L62EPcxySYKcRyHxjyowI5cftGKtbkxWp5jw/F6JKahcIk0LnnLuzXy
Lt1/TzvoEHxgsw+MFXTF2KHpuq7gB8aBzVV2MXcA2jwc2NTvr7uaLAP7/g5s7vr2SNVCg1IO
8BJtd9MNeAY10MMUjd64Fwu/DDTZ4HXRCm3Xb2xZpuhIfNOltirVIowO1HYrDvJqvwnmnVyc
4nu+3kyZySq6OH7RmhHeG/+9M6nhER3emkX3XBs0BI1BiouWtNBd7Yo+JtnUrRYZfejrlBU9
qPGLVkjVyx/O5yQbf4VX882QdCVWePR9rhb5lne/j/8eg1ZcOzRX4/WtDDR+c8cmH+FtImg6
745NV3mGnsCf4NRv0G8qVbACc2CTV9g2LWAN9AQv0XnXhRU+gxr4URiAbjSqNuMqMdIL2++t
6A28O6SdoyMbucjTQcUaF3hQYsni3KWlTS5OBJ9JFem+kRFc561JS7vReXxGNTyiEx28NqpQ
KWZjwIlcS1yjb9pQ59jUMIgIs0eVOjoq81Y4HN3aLM+Roc1XRRpFi7oM0NGbJjNB3jLve933
rIAFvAOb3X1X0QrUC5r74n+ZX8CtTH3Jt/d0mBf0tzuwqd8fh+UfaNHygubKzrDBx559O3SB
argb5OUznYGfWOa3rZB1cx1UBrfkOd7rFvw5MuSCrlPV3qgpKzrHu0bQXZrVfU6ykejADx/B
IUUbodZ7cx34D6z3+MxmeLo2XP1bMisaq5TrvXfF5mOSTdn8Piut+C+SuhL4lIqrlizOjaKb
olO31uTV3ukvoY4GPk6GmrwV3W9hvidgdtYOzT6X7QV73u3Q7HNZQR1uDmy2rLMK5nkc2HRZ
h/axHNjsnsDxwFZ5LLLe0ys15G/cM4+Bn5jk+46CRnNl19W4KqbtdE3DXSs3b9wpNuTbNxml
8rDqIgK2VV4yyDuuT8rm2MhG2qtoV1+dXtHkjzWRtzeDvHzGMTxcGyqug5hFm6sItCD05dZ7
c2zCb8UoDMmry27C1qYssay8NWmZYxMmLaX0OnyDUlHLmbjoLe3+bWmX77yn4E7kwGYX60jA
kZ4Dm12us4HOZO/YbF3HBurOA5tfrsOrddnFOgL9/nfoVxfrzjAGfhiUwUMiHiqqXOAMRVuT
F6bj5j07xSaqdWOMPnrrvcB+vV9erJsiE3W3ob21MIfG50HWjMjeCbozjOHp0sQkQ2uF1Ao4
D5JguzfHJrRZq0bOplZpuO3elxfrpui4OFN/+fi+U803WujE77tYt0LRfVOxzlDhdGCzy3XD
wEfegc0u2KnC9TqH5so6f0GDB287NFfUydbB0tEOzS7VEVgo3qErZN2N4x6fOQz8NCODerdw
e2YCvcl1iSts9CNdv22n2NBWi1L4oBH3itaC6hrrkxtZN0VGttqLtqLdxR14oBzXfLWqO0MY
nq7McOUQIy09HAR/mzLdFJswU26N/SJ1Rgw+pBaZKctlsvXnJJ26aa+jxLxyNAKhLYI6dat9
t6rL02z//z//73/9v//zH3VFK+WT2UNs6jBZBoESaMGTeIHW/g63QSvR4A7OsuzYXKUdzrTo
LMaOzVbaDN9mAU1dXYrefbCW8YKmfndaN27gS/nA5u4ERjTQYp/vwC54kNR6M8RyxmPws9QC
6dJbFddz2sG2urhoARu53Dt8TLLhzYnUFt92EQMVKq9JG7abAdI5NrTx6C7oag8jGvA5tyi5
5NI28eeN9uMZmbKxSGtKxYZZAQs4cdUCOnQzqjxLx7iYxPlDrWrgNjWuWkFHr85SPqfpqDYr
pNRGGQKWUf2qdxl1lbT7lmHlsg0CLUwPbLbC69XAzvUdm63w4Hi/A5ur8XSTAY5TH9hcleev
KwUrfC9o6qeTunW0BeLArtB4d8MGZ04GPwsv0NLCNa2NoQNuelpRvXaNd+01OMfG5VoptTgP
GtYYTf1YYRLij5drP5o5Nn5XW5zEttKZK1jooiX6OwILf3Wn/XjGxuWaDi1KWka0pWKL41et
6OQsv77VHtMxjkp3bI2sNPBcyq9aoVlffs/399pjOjr8QdBZm9904HM3LnprvDUaL7fA010Q
oRFrBza7A7KCrhk7NFva9QYa+RzYbGlnDZxrObC50q5tIuA49YHNFncG+mjs0AXygetNVeUM
o+CneQe9jCL+9jOBHdPmkuT/VdrZtbnvHBveWMz/+JOoSAGVt1+0pHx3yeZzkk1Iu956bVL7
GAWd8V0k7W42EWcWxSM25ZXh0qjVymrok7EsSXGheqm7P6bp+MoI1V6klcFgw21ctYJO/+W9
9piOFtFmZioqBtbxy18aUPePMRsMG1y0O+LAZks8tICyQ3MlnoXJNjjismNzJZ5t5eU5j3x9
OzZX4tlGClZnD2yuxBO/48GTmQO7ROTdVFXOPAp+lnmg4R9rXeRJL9SKA2e5tEv7mCTDfh8o
i3BU8RS8u3nJrG/tdnUM+DnJhvxrdi1kzdQGo7vZTZdEEF+y+Xmj/XjGxtUaNWaXJ1TKaGA+
tF+14lCztpve20k6bdTWyB88Si6M0CPnFZUGYr5qbvicpqNSC9VRVNtQ8L1aJh8Eb433nU6D
3XfC6MnTjs3VddFxBYZJHNhcZaeb71Th4eXApq5v7VtRrPduh+aubnMpDntcv7C5n8+1WkFT
pnfsinPZm2QuPrMo+GHcgapW6V1aR5/nftGSnJC74t0kG/MboRWjJiHvQDZLNLfxTe/dJBvt
xYppIRlo3OXsAMK/HmTexA3yGUXxiI1LNGOtY4iWiBpDXVyWhMBdd6t9TNMJBVTF3ysxJybw
SeaKY2a+c5CepVNdbrPTGczo+ONsovRb2P0GhoN9MwFL6Ac2u++uwq6kOzb7cJYKmhW2Y7P1
nb8JwcPjHZu7vhYHwqCC2rG5n0+30cHRmQO7pHJ3fWgmZwqFPAs6qI27mT/ZW8OnK5awaZcq
4mOajVXWUQuLuW5F+whXRGzXfvPWnWXTSoTASQnPSrBMHBctUXi/vNN+PGPjWq1Hjyf7XiLa
tFENwStqXXRTJZ6l4wLPN0XM1dR/P/B55grBypfT2Z/zdDh8qlzbEcd+AqUzVVh9K7zv9B3s
W0Nb7g9sdulOGH3179js0p3vUEHptGPTS3cVnerdsdnFu95QX8kdm128aw30kz6wX1y8kzOP
Qp6FBFRVLqUN6xGv8bsU72bZmL/2nJBL6cHgmX5C8W6WjXaqUsKRIHKLc4t3V2x+3mk/nrGJ
8Yioc/GodQzGT2WXRNlddjN8TNPxvUOobqfjG3Nweq6sOTNnvYpN/JynU/z3X0hdrjaDld27
drdA2X1L7W5spGCn9YHNrt2JomezOza7doc2yuzQXHk3ttLRlLodm125Gw8qdyO9chdLhp7N
7tgl8u76xEzOSAp5FhTgkjHcxzqTCjwzuyI+trZyU06ZZGOlN1cPSiwdHMtcVrm7bnafZdNq
EWlq2kUUPTdf4RV6X7k7IykesYnKncUtxk0GPJS5qG53UyKeJOMayBfF90Sj+3cF96gtOWi+
jPj+nKfDStXM9Z3F3faPbrljWN09Ma3FvtMVVbI/2IdPOxiTfWBz3/nhoIVqkh2bfloMa7od
m7q+JL5mqAHtjk39/rSGrRo4yrtjUz8fW8TjgJMEO3aF5rzxaZEzNUOeRRloGTyGv6MiTD7Z
p+Xai2+OTXjxFQpREz3rA3RN35bsB+zGkHiODfljIZQNDesuCcAf60YrZFq5ic6RMzTjEZuw
1es0KrfIuoZD3VYMWrtKuyrBfUyzMZJW/FfTqFYWNNFkRfWaSK9nimbpKFksTLHCr/3G+6w4
V919mxUf6NZyYLNbsgpsxbdjs0VeBztnd2i2xOuGNrTt2GyJ1xQ8lT2wuRKvR4809tY9sEsk
3rVfi5wJGvIs10BMo9fbGil1NK1qkd3yzanxFBveSguB1yPulsCuJl6Sdngv8abYhMRz9U1N
1NdIwcT1bYnp47jMVP55p/14xibUWrg+imjrzLjf8gqNV278WmbpmK+OizzfTbAQp/otl0uj
xM9pOiqu7cgfpNIGOgrwtxYW/xFefP6khL34ApvelYWGjr6g6dpOQAOtA5ur7nTjAmZNH9hc
def/T0zaOTBd16Gl4wP71aW7M6pBnsVoaCGTEWOWRKin0KT91gOPljk2HEqolz7ib1erqEfL
CiXU7do3Y45NSLTRmpTaSQgM5V5UuquXa/PzTvvxjE2JxwdJDdPHIIXRWeTDR3JzYDxJp7VR
h6+MdLYCZhH4VUuaG/vV/u5zmo5ETrT4N0Wjo/n0ftUUnbeu+318+OAT2gOb3pUFpiHt0Fx5
Z5sS+PEObK6886+kgz/lA5st7waDR1IHNvXzSdlKB0vHB/arRd6Z1SBPczTUGo3RK3VBu+i+
/nx2ig1vNcYjuvTCQxgrRcZFX128m2ITIs9cfffXpARqXbBK5N0MF51JDY/YhFwLhzdu1e+4
gudorDjRrDd+LbN0mplr1khatl4InWBZYrZM5aZ4N0lHut9jo5A0Vob9WuQdpPHvz3ykG/EJ
OD+2Q3NlXdiPorpux+YKu7DWA1+TL2jq2rqU7KBPwg7NluyGbikObHbT58B7Pseaul29OSU7
MxrkWX5GFXgcvq5pTrs1ZplkYU7D0Kn5NXMdJlf6+nOahrIMePh4RYhJ9Pb/6pb68YzFa1y3
0vCHrcTsQO647rjZJkzSiTH3qqXYEOug68+icV26nLb5nKYjQ6uvulFlfZVnMTrvoIwF2u27
vPYI9Jk/sNlHr2IVNOzYsdmHr/4QAx/KOzZXxvWtMfj9Hdjc9e1bKWhQ247Nvv+inAW3JtZF
KbdXXeD+3j2jGORZSkbVqq0Sqf+E0VZQv2gBm1tDlkk2xq53exyNET5/vKLd6V7ZTbJR5ghS
LeS0YLm9ROGV+ss77cczNjGxSzxKiXO+mHZFFd6SctZlL9rHNB016dzH4MLCFRWsa7z2xk11
bpZOGSQaszqNCCwFvx1Z/kyvPWpgB8SBTa/PDVA6Hdj0+lwz2GsvsNnSrhawBnZg02t04DHg
Dv37K3R3PntnEIM8DsnolUcPK1g4/WyRhfJNZ90kGytWxEyVKprtl1Gwm2SjXDrV0aq66oZ9
9pbIupuQDDljGB6xiRKc+u6BOXoeBRzOWSTrbgt3k3RUpVo38+dib2Agy6LCXe03dt2TdGS8
LKGlNn+Rgxvqd+HuDzba6/5SAh2EDmzu+1W3Cp++7tjswh1XPCQjsPmFO3Dy6cBmF+788QkX
7gKbff+hzey6Zuay0vU7V88QBn0YkCEuhBr71qxoQedhl5zD3hXtZtkYWR0kry4n0Kg3oWg3
y0Z9WcilQzjtgQ/iNbnDt0U7PSMYHrEJnVZivJelMGwXtEjdsV6ru1k6EWrbzMTv49FBQ9Wy
xuP6LgJtmk6tOlyr1j6agnv+v7Vo9yVGe+gZz5rznWXzHPlWewPzMdih2RWd1tA50x2brTgF
HUQ4sKmrGzoI7S86sKnfn9aNCRw0ObCpn4/bNgw8UDmwCx4lXK9dWPTMh9CH+RBkfvOVFrbI
4O99Td3qdpBjjg1vlbiFV1jMPoAH33HREtV5Pa07x4Y2UhdoUYZTrqDPR1y0QnVeauifd9qP
Z2zCT0W1aIzacDe0eW5FZAAxX7H5mGbj+5tijahGjyNaglviwfIaELy/0x6zUVeyg2yo0+qg
EXFc9Tdqzn+S0Z6BXiI7NLuoo6hZ04HNlngdzNveodkCjwdYUjyw2QKvCWjyeGBzBZ5tAzQc
3aFLioo3L90zH0Kf5UNoMQsT5R5Heck+yjdFxSk24ZfXqKrUyHYFb26/aEUSya28m2Lzknda
pI3SVHLlXb1snft5p/14xibk3ajNhbeqyGip+o74eo5olo5x8V2RDOlNDR6OWCLw5LLk+zlN
JwrYQ2s0VlnFi4pvk71FAi/dZE8Id2EJbK62k60P8O1/YPO1HRqEvmOz1V0kcsEH7jX5QDa8
VcCdxQ5N13agyUcglxTubo6LzxQGfZaQIS7oYnhvUFQgUPvkFWzubPbm2PDGtVd/zZbKRTv2
tuUlJh/11bd69badYhMiTYb5lqUw+hReJuyuAzL0zGB4RCZc9sTiqLhJNwbjPuOqFXRuDFhm
6TTrLoAiXaYN13aZBixMN5W7SToSHYBsroGHMZiUE1e9hd0iYfctLnvsmg08xT6wufqubQN3
7BjJ6jOc8xRtt9uxuequbQSKzx2aq+3atht3IOJux+aqu7ERakF9YL9a4Z0hDPowIGO0NkoZ
0aoFElplpHx3NDvFJuzyhhQaTVq8gVEj5RVs+qUo+pxk42qNWZvLk0HFQGOTuGiJxLu2/tEz
guERm/DYk0FORtXFN/heWWakfHM2O0mnuRIqVGLGundwGGeZkfIv77XHdKQN3000VuLq99zb
SDlN4uV77JUKTske2FxZR1sXVNft2Fxhp1sr4A71wKaub/U1g8uKOzZdtito4nBgs7s+B4PB
8Ad2xbHszSSvnjkM+iwjo2p44/feoiEK9txbIVRvZz0m2RiZiGmlWkl/n1mPSTYx9qpsrlVH
BYOKEiZ59UxheMTmNcnbKcYiQkWAu4hVsx53x7KTdFx0u7Yz30qUUXELviWnzOU6I2OWTiQG
im+JrPkeD/zpvCd5/2gLPkWTag5s9sGsEerTsmOzD2ZrA3tlDmy2whPQ1H2H5q6uuWZTUN/t
2Oy7z19W8N0X2BX6zm6mKs4IBn0Wj1FfGVuNrZaK5rkkzPJOsvGfuVrpZsUfSGjYxxJ91y+L
XZ/TbJRKOLxR6w2dcKuTre5PZnnPAIZHbELfuaoLt0f/p4EmRxmzvJN01HQ4j1GlChwnsWaU
V2+67mbZlCaRODxc5MEn53/nJO/fbr/HAu7jD2x24W4o2i+2Y7MLdzrAccoDmyvrXAwZKJwO
bHbhrnfwTPbAphfu0HbPF/Sry3ZnKoM+jMhQkkJUCinD0bZf7qs8y8aIubhSbWqksKxb03N3
U7abZKNMYxgPq6yaOcjst8PNieyZzfCITcg6V0GVhNhiBBiVdUuOMC9V6sc0HVUdrfriuORW
xlZnWdnul/faYzoSmSatubSrVMHn7jv17A824BsbtQEa8O3Y3PdrTHCiB7M7NrtsR6gAOLDZ
ZTtu4Nj7gc1d3zDVAwcqDmx24a6DlnU7dIW+o+tAeT2zGfRhbgYZ99oi0nLAGWJ1RaHrVt9N
sjH/HbXzL1QRfX3ZbpKNEnWJhkiXRDCbNWW7O313JjM8YhNKjczCLtoXqQw0mWGJvqO78Z1J
OupyNX413FsrubkZr2nW+3vtOZ3CytyKWIuxin/0sSx9hQUfeIS34vTukUwBFcqCR+QCLfxN
toBtgEd0Bza70lkq6hqzY9OVcEM7vnZs6vpywyvZBzb1+1N/pzfQuPDApn4+HpsU8PdxYBc8
TLjeaOEz0EKfhAzEsIJEN7t/QmtoeMqSCYf76ZMpNrzVNlppJk2KgfUnv2iFc8zLuP9Kn0yu
zf9YGe4Ym7hoidq6OcI+4ywesYkDTwmv4yKl+O4LNp9bMX1S2nWG3CwdV/TSSPqwEg7OudaA
v7zXnq+O+g9mSBVlbeAmf7Z0+7tr4X+SNWATsFv4wGbLvF4JLIjt2GyZ1/3nDxvIODZX5o2t
MDjpcWBzZR5t2sED9wOb+vmk+j2FPdp36BKRd32g3c5ci/Yka4A2rmxhVhKjZODtSkvmPl3k
XVeh5ti4XnOVJ9Zedocgm1Xuz5fl28/ptRHzu5p6sTZAUeTXLElgq9fugO0MtXhEJlQEKRfp
ZJXQEbNFCWylXfX3fkzTMRF/JHKPcN0Gzn/HVSv6FOm6tj69OsP3E8OMxLgSfDz/Ps9epPGS
3QEjEAPstjuw2d1idaBxcjs2Xdz1B+Kuf4O4Aw/bd2iutIuqIfhCO7DZ0s7AVoodukTaXVW8
/I17hke0Z+ERXGshG5W5oU7Wq6TdzQHjHBvemK0Vcl0XxRXQl3tb4dtU7bJE9Dm9Nv4NsbZW
uwtW0Ft4lbbr18NO7QyPeMQm/EkaWWEeMVLTYQu6JWfZN+4xs3SaRe6x6zoi9mXKdI+5GzGe
Xp0xhNQfBr7VEzCS6m89y/5HGQSC79gdmi3w4gcGzwM4Nlfg2dYq6iOzY3PbUXkjsMlmh+YK
vPhGUIG3Y3MFnmwGjjvs0BXNinLty9vO+Ij2LD5ClI36YH9fFcNGJeOirxZ4U2z8LjX/lUeQ
6wjditoDLon2uDxu/pxeG5UyWMh6UXQzQWvygmu/Kd6d4RGP2MRRa6/U4gBw0ABPXWbTwf6V
zl3xbpJOJK60TsxVyytSERN4C56i8f/81b32fHW4hU8I9WZV5B3tkekhk/va71sVbHu1Q3NF
XfX9NuiXdWBzRZ261EAjeXds6upGN6KCgXIHNnd9w6gb/P4ObO7nc602QGulA7ukcncj7M70
iPYw2cNftiXiOAsTugvxixawuZtCmWXjGpVaOAS6TEVN1xdNoVz2qn1Os9Fu/qc31WpgA0Cd
PCj7X+YxN5W7MzziEZviu4EeITJaxOnAx5hz4REPzAFn6Wgr4bMSC08Mh/IumTK+7ov8nKdT
JXZ3Wlx1Ky673/YxC4Tdd5kDGlg4ObDZTXcF3s3u2OxzWf8Z4uaAfcWU7BOFx1spqELZsbnr
aw9S+Sw/lY90GxXtUtuxSxTe9fRnO9Mj2sNkD6pKptIi7wxN5V2h9+8V3iQbI7auvdWwKoEV
3go2/bIQ+TnNJtakh3W41M6omXVbknbWr/Of25kd8YhNnLKybxSLsG8p0LmkRWezTNezFbN0
1ITY9ZAvUq/w2PSSOWPmmz6AWTqugtWi9dZ/l/jZ7NTm6K3wvtcgUNBgnQObXbyTZmBxZ8dm
F+/C4hQ2CGwrZrSfSLu6DTQU7cCmF+/Q7+/AphfvwJ/HDv3q0t2ZHdGeZUdIrXXUppVEwFm5
RaW7Vm6E3SQb13NqJK7s6mio3eHXl+4m2WgfhZ2HCSv4qFtVutMbYXcmRzxiE6U7doXVo7kT
jpApS47/b6ZMP6bpqDbR0iuPMCeFDzGXVCLvNhGzdGqJuDahHhnDb+fnTGH3TaW7jr7ADmx2
6U4YNZDbsdmlOxb0FbNjs0t3yqBB4IHNXd++VQWb/F/QbPVJ6FPwwK7Qd3RtVdHO7Ij2LDtC
/P0UViJGrOABk1+0YgyhlWtTlFk2RhQW0MNaGWiozqLC3eUYwuc0m/B3Ma5R9mVwhtEvWuEi
UvvVWebPO+3HMzau1HrVLv6nR94ZKu++OtZjlo3a62jW1VB9ULZbE0L3yzvtOZuYpDCz2iLi
FC7b/ZUdd/wV9oDgd7riJfsnG/EJ6JBxYHPf+eGsAL5UDmy64oSzgnds6vqybhUd4Tmwqd+f
VtdpYLvngU39fGwbow4yB3aJ5rxp0jqDLdqTsAFyta7CvTSKaCx0WHSJR+mdEd8cG/+hi4jV
qsOcFOiTuCYZr9vNnMfk2tDgYo3N9c0w1IhvReqja85ry8d2xlo8YhOjor4o3FptUSeFZdqK
s28q16Ejs3SMtHWWzmPsG45MI76rHcHnNB2lUYcNtt4GGpb1Piz+8434+sBu3R2afWw3OtjU
fWCzRV7soGGnFlmRe/dM5HVWcNpxx2aLPGXQBvLA5oq8vhnqRn5gFwiJOm4Ojs90i/YkccD1
WnhnDG2DpYGFRVqTPCKXOXkfk2x4K9pDELVIQUZ9+JaM49hldtnn9NJwIR4qRL0OcPwuLlqi
8W4cH89oi0dsQq2py7waf4S/eKjgf5XibsxaJulYZG1xsxHWj2Dy+iKNV+yX99rz1RGjKhFC
VGGHjFmbxLfG+3YjPopUI9CIb8dmy7sG/qZ2aLq4I7B5/gXNlXa2oQfGOzRX2Ok2GPVX3rHZ
wq4rGONyYJdU7268M86ohvYwRoNqKa7sxNUQoy4tK37n9y4tU2x4Y4qRxDIGdwN76OKiFcpO
btrvJ9eGy+iFijYrqJ/nGotEV3Y3ho9nUMMjNtHbR2YabQ+kBR/mXdERWO86AifpNLNO5KQi
SwM9AF/RFkSvPcv9rfZ8cfwW8y0RWWuM+hvNzuG8hd3v48JXVbEHy4HN7stiBTfoBzZX4Zlv
bQQs3+3YXI03/N0Glj8PbK7Ka1tp4MDxgU39fOJPONTH8AVdovGue/HtTGqwZ0kNFMlVbVQa
vaLz3dsKe5zbE9o5NuGnHt5Mps1fvAOOSluxNnfVu9m14UJx4Dx4EJyQvqp6d10mtjOo4RGb
EATUeyeptfQOvlmWWS1f14ln6TST2ljYwlQHtPVeZrV8vZ+YXp3uT1DWMqz4cwBu2nzHaPz7
Ux/JTny2jQaWJw5srrCjTQsejxbYXGEX/nrg4+vApq5v+BOi8wovaLZs7wVsADmw2WXjUtBh
8h27RNhdN+HbmdNgT7zzfWWbaR8UBquE7kM2XmFK/Epju3rbTrKx2szv1RpSCGazZNzDLmMa
PqfZKBtbZOs0IXD0qa6xWC56PVhkZ0rDIzYuAkSpKnMdWruivWprxnkvZ3E+pumo9m4j5nk7
G9glvGicl27aPKfplCJ9jOj8oIYfmr8zNBYIu+9y4uugnceBzX7DCqEnFjs2+2g2ptdgJz5d
EfDxzGuZUbuRFzR3dX3HAPZ87tDse6+DRbsdukTbXTe72xnRYE9s812m9bAQ8wd6tSaoky+v
OGa+8+CbZRPWe9267+Q6EXbvLLJqudV2k2wiaaJX6mGSCI5VLNJ2tV+7PdoZ0PCITai00cqg
COEa/q+pLss3s7yzdPz2rS68rcgoAzZZXjLLe+PUMs3mVUmNZGLYW/Rt1PJnOvCxYA/GHZpe
sBto3/eOzS7YaUMF3Y7NLthFyABasQtsdsnOHjig2BIHlIclO7Qge2C/umR3BjTYs4AGbs1f
TK7plA124FtUsrt5106yseq6IaJorApqf7moZMfXTVCzbFRIo4pSSx2Gslkj68ZNye6MZ3jE
poQX0JBKWlp4AqE5sSvMgJzOL2+1x3RUuYXXTCi7Vx71F44ewLPMn/OrM5r57q7aUHQz/a7Y
/dEGfIPAVrYDm/2CHYxmK+zY7IodM2rev2OzK3aEJga/oLmr27fKoH3hgc39fLpVtN75gi4R
d9fDi3ZmM9izbAZuIkX80a7h64CKuxWDpbfibpKNUVi6tGZ9DDhpYpH93k3z0yQb5R4Kwl+3
XTvKZpG4uzbdsTOZ4RGbqNmpRLxyl9YrWDdYVLMju87NmKWjpkVdCA2X9TxQrbqkaHeXjDZN
p7I20uZLNKjB6u6vrNp9iQEf+rZY86pYNuWRbsHHBZzxPLC5b33e0DzeQGbrTergpzuwqWvL
fWO0IHtgU78/rRvYAfhCpn42tq0M0FrxwC7Rm9cjlXZGRtgTG3/aWI0pju5KcaWGDg98tfXe
HBveaq8umweZMdocHBetKCZedjN+Tq+N04hT1SaE9svFvnCJ3LyeErczL+IRmfD9aP52KF2p
yAOD5BXFN9brMfFZOsZWdMgY2ir6FPWrVmwGLp33/hsAAP//7F3bruy4bvyiCCIpUtIPbCBr
fUWAvCYB8v8PIdv2BJgDa8oaLe299vTcznkoz3S13VaJIqv+/1F7fndin9bD/cd/P2BE+9t5
77s775ErNtCA98TurumogN5nJ3a3wmulwBXFwO5VeDUxaAp6QHfruwpa7xzQ3QqvNzCl6cQu
UXiDgcorNKI+sfJ3RRC9hdWFkTHaNxcXLVF4gy7AKTaScs29565cGoPdEHHRki7AwRHe7L3R
aGeUGjUrtDchrXjLucQbDIlfoRGP2ISI8E1s6bmFJzGsIRbs3IbeyrNsKoeNoLkENy7wgMcS
3717j/XP+Zvju0d/vfiWglTAEf63wvvGvnu1gqeJJ3b3YXFDx4tP7HZpJ6A0PrF7pZ2lDrvH
Hdi94k5T7WAzwIndK+9aogKaVJ3YJfJu0Hp/5TPUh9kZfm9Ns0aDFqzuFph/DM335shI8p+R
67tCTDUTuHNZYlfn/73BTOXkrWEz3zJXypYzbKvMK6w/Mv3lg/bjGZto6zMX9JWImCs8R7Bm
fndkzDJJx6r0xhFAx631rcYs930jn/N3x3LVbJK1d4bNBOc2rW959+u47/mmHlR5B3avyqsp
ZzQh7cDuVXk1ImfAI9oDu1vlKerScmL3qjxLvkkGPZYP7F6V15OrFPD7O7ArVJ4MOvGvhIb6
LKEhtxKLLpn1AkuJFSPx42PaKTbi+rNTY/GFKleQjawpSdYykHmT94aVoiRpYqWDbu1x0QqZ
Nxoav/IZHrGJmQ/rRFZyz65a4VHeFQebUgZVvEk6VjkmjCpJ979Q1bpE5o1MlqfvTuVs3Zr/
KitugP32WP77Mx+b7fdaygQOkJ3YvcqOUwNL/Ad0r64LQz15YL63wvTiwd2lnqyB1bsTu/fu
2oPQO9sfeseSYrlFGz8Du0TXDZrwr3yG+sQ0P8a0s2uGzN24gn22tOQAcGzRMsmmcvMXke9C
GjEou3dYtEyyUSm1ZmVRIkbtc+YOzP5F1w0aPa94hkdswls8Z2Iy5lwJHhddYRLBIncNax/T
dKLtrrwyxOLnA497LJleyYPT2dm74zsIjVOu0oqCP533MO83tt/ryR9ccJj3wO4+nzU0gfnE
7j6f9d8/7L7Xt3u19I6aUx/Y3XXZjobKntjtTx+hgz0Hdsnp7P04b7uyGdoTv/wwzm454m57
LwaPjC5RqyN9N8vG9Z3GEqUx/7pV37V6d6D5Oc1GOedGLu4segpRfbeiXW10PNuuZIZHbKIC
18yFEKkSt4qeZ645nh10AszS0ep6NXNuORQrLIiW1O36Xz5rz+lkJv+apPl+osNV1be+W6Dv
tpvwaQNTeE7s7sJdf2DD13+GDR+jU7MHdq+0y6lmbLt5QHcLOzLwlOPEbi/cCbjtObELxAMN
CnftymZoD3MzRFRZqGVCp1jiogVsLN8tTx/TbGrpXViq/1Uz7K284NkemvDNstHiqi6X2rOB
LairYjPofnynXcEMj8i4QgtzxFYtjjAbaP8Vp7grdN0gNmOWjoaxa1bfQ8TjBrsRr6jbZbq3
BJq+O519h6dWyJT1nYe2U9f9rLqdgs2vJ3bvAqupZHSu4sDurtsJOht2YvfKOw7rOlQd04pK
zTMTPjbchC+wu+t2raB1xQO75Fz23q2iXfEM7WF0hiq5+uyuIQg8CN9Rt5tkUyUrN22FegUX
qR11u0k2yrn10nKPoHnYY3lF3e515DB+0n48YxMVuJB3LNZdFYFydVHdbhSdMUtHQ6la5pJL
loaWIddkZ9yG1n3O08mvoRfz/43S3T/aho+/vQ3fI6ECapQFL8kFavhnmQN21D7mwO4udWZD
u9gO7HYtnNFjtAO7t0sxl2SoB/GB3fr9KfsyCKrNE7v18xVKxODzd2JXFDtvbUpco1ypFu1J
0oClM8K+RNs5+GL0i1acyY+mT+bYxCCJZfXlPPf8slLDpk/WmFLfdynOsWEXtlSYu2n4eoAv
u0Wn2DLol7gyLR6xoVSambbWyLiA+do0WU77MxsbFDun2ITdn5KaWFMRNBspL6mrM99uIz+n
6fgGkilrJaoVPfSY1fa/uhj+J5kEMuoIeWJ3q7wGBwUf2N0qrxN44H5iN6u8WN/BZsULvFfn
laQVPDQ+sXt1XkwQgR0fL+gKlaeDmucVb9GeRA5Y4s7UTH0l1AI+D3HRiprn7VTuxySbEGzm
oqi2Gqey8IzxklmUW/fkz0k2nKxHUgc36Qyez3OqC1x+xiLvyrZ4RCb0mhgbldqIwU7FVSLv
9qjgY5KNy7Vw+clxTE8En8/XJT4yt+0Gn9NsrGSXjhaZ4YxaqMdVb423RuNttgmUJA3rZjug
u7vF/CkE97QHdre0awXsTT6xe6UduR7PaAvUCd4r7Voq6Nzrid0r7SyRgDaBJ3aBgOA+KOFd
WRLticG/JctCvuTmqmj7SlyzQtvdeh5+TJKRcMGQYtpzrwaeZ8ukC8aftd1tlehzko3rNBd1
YY0UBr3gHAqvSZLIt82XfzxoP56xORpjW1X/M6M2w2saY5lvY9g+JtlEAzdx45yjjtcyepy9
RHnfJyB/TtNRlWhiyNKtKxjIOBvC8lZ3v45LYFXQhe/E7pZ5HS1Andi9Mq8mRVuVT+xmmccJ
9Q55Qbd+e0YpV3Ak5cTuPkWWDh6cndivPqW9wiTaE4d/SyWSMYyp+aJl2FJlSww+xhpvik3I
NW1UWtdaaoc13opxoUb3QR9zbDh1/5fmkN5KaM9iXPTVGu/KknjExuVaKT26+0wpE1rAW/G7
4WyDAt4Umwj66NyEangwoZvRZUEfgwreJB1jda3aRVwcKqMjKfYO+vjbGm+/R6AY2D92Yvfq
umijR108DuxeXacpek1gl0DHbr2/0qMnEXYvzktc7p4NG4uB78sTu/fzldQVnZY5sCuUXRsc
mF1BEu1ZkETpJeIKmKQK2HfDSw7MxsPGU2xi2Lia9Vx89cM9D5cMG7fbCtHnNBvtUlvV6O3r
uEvg1x5m/vGk/XjGJqeWI++sSI4BXXAT4VctcQnUOy30MU1HTV3SuejWagTuIla5yPz1s/ac
Dmm3XMSlKmWBh2umltW3tPsFXAKbv8VhgVd26ztOBO4vDujuw1ky0MHwxO5Wd9rRBLcDu/fu
hjkR2ld5YPd+PvOdLjh9dGKX1O0G1ZQrP6I9y48oJQIXyEwyVdBaaMkAqP9HBydmU2xcqFmt
/mOqJgKSoSXdUC7A7oZzP6fJWDGNfN6s/ic6OG1Loj1G4u4Kj3jEJmSaabznjLiDB81+0YpR
EbktQn5Ms9HWpUhRytkY3OblRcq7DrTdLJ3Sesm+fayV0XXrfTT7PR0CGW0UPbG7y3auJOGy
XWB3l+2042W7wO69v5Jgd9wTu/f+9iSEWgQd2N3CDu2CCuQSUTew473CI9oTQ39OtZcS/sLi
O3YCN0l+0YrD2NFaO8WGUnM6PVfJWdFRF79oyWFsGxzGTrJxHq6B/B+kr3P4bXY4ruoGBjJX
dMQjNjn1LL1rV/+dGpjFGBetaLjTwcjsJBvLLb+qXFq7wTEltqIAWWjQ2zlJR33f7qquFWG/
OV8bU/JWdb+AP2BLHY0ZPLG7a3YFPUF6QXfX7CSDNZ0Tu/fu9lQEdIE6sVu/P5FEhN3dA7r3
01FiNFPmxK4Qd7euYP/ukuYUEP2Jm7+kLBxTxq27ugP5+DUrtF2/13ZzZDjFYIhpGL2jm4I1
XNrtQfnnJBdKnXqvOVuMycJxKytCvZluQ8H+eMx+PGWT/V/KrhtysVZQNnmFFKLBWewcm8jU
tcpdrIe1JhzEu6QF0v7ySXvORrpyiYBAyiqwTv0t52TlK4wBwc6QFT1F39iAD92NH9C9UtMV
BoPDpyd2t9hkBZuXX9Ct95Zy5NaCR04Hduu3pxF1Cr7GT+xesVlTY9C26MQuqSTej3X0K82i
P4kY8F2O39qw/lD2/4dVEGIWZAGbkfneHJsY0qfci1qNgUrUloXWnA/fz1POseEkXJnCGtEl
DWNseM2w68iXpV9hFo/YUIxVc7MqvrMp6KtnyVg18yAheI7Na6yjWc4txlS4wKO7SyaR80Bw
TtJRUZOoWEukyKGCcy7W5lcXnP8s8z3QPO7E7tV4JfWKpskd2N0ar6Et5i/oZo1XUjV0svgE
71V5nKiBW4wTu1fl9VQyaA14YpeUFO97s/oVatGfBA34/oLYX+5Sc6aGTkv7RUtU3n166xwb
SS7xWHs3zgWdrY6Llqi8+4nKOTYh2MzX3ty51w6Ou/KacVei+/PifkVaPGITgi2HHuKoXIHt
24tUntw2z35Msgm9xkWrxWE+lYpOeCxReSODllk6qv6c9eJ/+M4CrGC/uwC/sf0eEWgvdmJ3
yzvtYE/Jid0u7xQ8tTqxmwVeT01ggXeA9wo8S6INdD85sLsFXhWwmfLELinjDYorV05Df5ah
oa4a1X/BLkEzWPiyJTkNvizeJ8rNsRFXN0JWtLXSewY7DpZIIhd494lyc2xcq2mV6Nak7os6
6s6yYtqe8+1B6x9P2o9nbChFlUiiLFn8JsHR1EsOwUfHxlNs4ti4UYTrlpatgTXWRefGnAcC
b5JOmF6rau7U6dVwCNGZ8zV6C7xfxYGPU20ZW2VP7F6d5yt7aeCL78Du1Xk1gek5L+RejUeU
Mty0eIL3aryaGM2uPLFbP1/hcP0DB2YO7AqNd1so8pX3SmnozxI0fNVlK68sV/8WQY23YuV1
jTco4k2xkcRarffoDuSGGvAtCXSuI4k3RSZ8G02ia7NkIbCuwktO0YcGfP1KaXjEJrz0XEA4
Fa49C1rDW1ORHMSkzbFxsdYp+yZFOndjRYtetmKSV/r9zMcsHc2xjXdlLzH0AdfwfsvM4N/d
gC+j4QAv6F5Rxymm/dFZj8DuFXVhqQfKkhO79e5KS01BXXdid4v2DjrSH9DdpeNsFdxSHNgF
ykHkLmDV19ornqE/i2cojcxXpiaRGItmby0xIrY8KKdMsaFUqcUBYPFNCPru8otWSNRa7sNv
Z9moVFHNzkRVsXtDkz1RD/xZ+pXO8IhNmO91qbkUbr0xeNC8ynxv1IA3SUctFw0TbymUDdZB
K8qq1Ac7iFk6maRVvzu+f0Br3nHVW9b9fVn3k0Z5LYOxGSd29wpbCqifTuzuw1n09CGQe7Vd
x0MfTuzee+vbBdQ15AXd3vVJ6GTPgV2i7Qa9UFcsQ38Wy1BEqPs2vTMpWGGOixaw0dGh7BSb
l6+JEpuFTzSa+rekFYpau4+8nWWj0uLsr1uhqmB5fYO2u1IZHrEJleb3JhfqvtPJYGbdIm33
ytgdP2qP6fjjW8LewPxvV/aoGFpxKiu3dD7n6RBrYWkll6zw3XmX7BZou+3me0JoWPuB3V60
Q83jTuzuop1v68Cz2AO7W9i1znC/WGD33t+aCmgke0C393sa6gJyYFecxOpgaPZKZejPEjPU
JIp2ZJVVUVuTFaUHslsXsY9JNuGpTJKrL07aW0U7upYUVFu/d7qdZaM15ktfR7EdbetYIx1e
Z6XjJ+3HMzbhj6xVNGpcJbu+Q4XdkjHTOijaTdLRMGmxYpXyk6LdkvGQ0VnsLJ3clGv3t0Bt
aJPOW9h9Y/+9yMEC5d0Lur1wUsCy04ndXbITBqcBTuzeu0upo+ruxO4u23X0+zuxu4+M2dA6
14Fdou8G0xRXMEN/lpmhlaqyf39igg4oLVmlXN/dJ5DOsYn8CzIjK6UWtGNjVWjGbRnyc5qN
+ZrbpFGNXGC0cLfEwXeo765chkdsXKn5/kHC+7q7vMN+On7RikPMUWjGLBttXRuFgUgjtOd2
UWjG0BRllo5olGiYciM0rOh3NUX5Ehc+QocXV8wtfmMfPt+7wEZ8gd277EsyBhMzTuxu2ckG
jp+c2K33N/z1WkPPoE7w1m8wHPYI1EEnduvnk5qkVtiNL7ArhOfIje/KjuhPDP19z9PU/O/I
4i3gExEWfgvYDN34pthIctlZOmuu2fXaTjO+eps89zlJhhP3qlmN41AfNPbkJGtGPAY7nCs5
4hGbcFzRxrnXFk7DqEvLGrfkv3zOHpIJvxVqrF1Ns+HHxUtcWsQGrQmTdMKkpfXSJVtRuFFz
zkH2V5ed/yQvvqzYL/GA7tV4muDd9ondrfEa6mR4YjdrvJIKgRLlAu/VeJwyarj8gu5VeM1X
H1DgvaBLCou3mQuazwSJ+D9P9B31Ho6xzK1n0APXdyRr3JZvR3gn2YSlnkgtzZdcamBb0yIf
vppvO/An2bjAa6VTJhdE3cBfaly0QEQMfPguNj+esXGxZl1f0+LRgbrThi/bbT/gJJmQahIx
GzW31mpBC3FrBN5t0fdzmo4W0pb9F+mvAmH42Pi3rCv+A2z4OPn7BLThO7C7j42bgjbGJ3a7
thO04fzAbtZ23b8U0Cb4Au/Vdpo6+p45sbvVnaLTvCd2Sf3utqyimS4N8SxNw5fc2rXUqHmB
9ls2uXPHLVom2UgSVw9Se3sFjILjTGsMZ1odrLpTbKKAF7OifncI9cyMa1YoonsXvovMj2dk
wlCv1VbNugtvsAOV1kSDDFz4Jtm8wts08icq15hS3unCR+22LXCaTjFTYgnL9Z7ByneeVN9v
fferuPBpYvCU9oDuFXk1ZdAi8IDulXg1qYLtLyd2r8Sj6NpFz5BP8F6JZ8kKWLU4sVs/X8m+
ZIEP4IldUsK7HbXUzJeMeBil0bVm7dZaBs3EbMkxILmsvF94p8hIYjZXRa1xlFbQI1peoVcH
R7STbEKtme9OzYpoBtu1Vh3R1rt65B8P2o9nbCKh2roLcJIsGYwapDVsWP/ySXvIxsWav3LK
OQGr4F4vrloi8W5HeqfplCqkytV8qVRwYvEt8b6nCx938Aaf2L3CjlMz8ODuxO6VdpoM9RB9
QbfeXWnJf8LwwWJg995dS2ENB9vwtc2VRY5oYHQk5cAu0A4it513muXSDs9CGkpttXSK/iQF
bZkW+fANvFom2YSlnvpPqZPLIAWtohd5tQx8+KbZaBjeunLo7PIO9SNeUVUdebVcbH48YxM+
fGyltDj1VQErBnHVCmF3W+z6mKaj2mrtLupKoQL+clb58LW798DnNJ0STt5WjaiTgQ5jbx++
b+3D1wj0uTuxu09nDZ09OrG7T2cJHZo9sXsVXk9Swft7Yvfe35aooOdRB3b781dQn+8Du0Th
Dc5my6UinmU0RKZYbea/ENePmCZa5MZnNGiJmmITYs0lkcTKmwvYXOIXLYlIu611fU6zUWZy
WdT8D4aPM1f8UscKr1wa4llEQ8tm5BIi99wyaHj09W5803R8g6Ixbh2GOhWms8RS53XmMn7W
ntPJpeccdVX/8YC9kW+F9z3d+ApomXRAdxfuuqHmYQd2d+FOOzpScWB3C7si4NvoxO4+cRd0
ZuHE7hZ2DI/0HNglwu7WQ0OzXuLhWYSGcpcurw4icJaR1/Tc2W3f/sckGZdoEZ5BlQv5CgWb
8S2YBqN2b5A2zUZVehNfcal0Q1Xqitm2sa7TSzk8TNCgsOHrJCFUwVfjqgSNcie6P6bpqJXw
48tazAo43r+ocsej/s5ZOi7qmlRupt1AF9S3rvvGZnxhcYZX7gK7d4HVVDJ6dndgd1fuGBZ4
B3bv/X25n8ItY4HdXbmTArbFn9jtz19B7fgO7AIVwfmur8vXXbtUxLMcDV8JWhhVmL/ewfM/
nnRZ/ReFN5iqmGITlbuYL61RRyP8bHaF+K7lTq9+TrNRI19wS20ioAcUrZEQAze+i8yPZ2TC
N7lEkJGUas4JPctc4rYsOhB4k3S0dsk57Jaz62/sUVsVo2F3UyKf83Q4IhJbV2lC4IstT1aJ
f7bA2yff/vc//vs//+e//o2y/7F1fcLeFrs1ESiHFryNFwjvn2FHqCURg96eJ3Z3S5oqWGs4
sbtltxTQRPzEbr2/LgXJ0O/vwG79/kzjnmHf34nd+/kksjzBz3dgF7xMiAYzpvWSdg+TNMSX
Wleq0sJWDdV2K4SqykAMTbEpKUc+GnUlQnOW45oVqvs+5GSSTFiAFuu1ikpuDXXeWeG7ynnk
VVMvYfcsRqOETaT/lV2uKly5WzEDyLnd3ZyPSTqU2H+NuRTLJRsYChIXLWFz60Y4zYaqRPaM
/3Jyq6iT0JyL588W3b9WVfUnmhHqKx0E1niB3V3aUjjp5MDu1nhdwdLgid2r8SzlCg7hndjd
GkoU9Pk6sVs/Xy1h0gpash/YFWfnt9kgvvS2S0g8S9NQadzErLTSwWaFVRpPByvvFBtJ1eUq
VSqdemF0nHlRU+RA5E2xKUkiKU2yVGsETviVVJaMM4+sL9ulI56FaZRajEtrLSKKwbVldmL2
z6fNMmiKnKLjCiekd209TiQKLIvWdDYMSquTbERDgjfprsBRxTq35r813s/2I6w9zEGxtesF
3S3tzNB5gwO7W9r5Nggu3wV2t7TDJ3Jt0UTuE2nXU8Nely/kXlknyRpYWjyxS0p3gxPzfkmH
Z/EO6mLOcgyIREwx+EK3JS41PDgxn2JTEkkrVEvupaC7Pr/oy2XdJBtX272qCzutGfwp+EVL
rJnzYAPRL+XwLKxCpIvW0l5yCDR68KsW3JxBB8DHNJ1wVcy1uALOorAT4ZrKqgy6MybpdK4s
Lre1sTI6zNzfSSKrhN1PMSKklNHBgxO7V+FZMgFX2RO7V+HV5G9m3IywrijuPFF4NVU0Lu7E
7lV4LZUOmjme2L19J5rYwMGhE7tC5d3GIvy70pVYQc8yHiJr1dfeXno2dAR/SXsX6a2S+Jhk
I6m5ZlV/G5m5LEKLd32FZq3tfhphjk3Y5HPzJ0dby2CzTFyzgEzv9we0dAVWPCITco393piL
CXK1hw6+fLnIm6XTil/Ri4o06x3VrCvuDufbNs/PSToRBsb++2/FVPHqXZ5i8xZ5P9OK0FI2
sMn6xO4VduwbIdCL4sTuFXaafJkEfyAHduv9pZYEtSI6sVu/P9FU4RS2A7v380ly6YDd3xO7
pHx3X1ShK6qCnqU7UA0fwtp8wTXY8G5Jcq7RvRnhHJvISKtWXdxJa6h9yJrkDWr9vh9qlo1r
31pK68Ja0emqNQd/1O9tL+mKqnjEJtLinQR1p5Tb69QXO5VdE2s82ENM0qlVey2vLk9r4CGX
X7Um2Pgvn7XndDhC/LhKLRXtWp3NvXtLu1/AjLCmzKAd8Yndq/B8j2roS+/A7j6chVM6XtC9
+q4nKqi72YHdre9UwQyRE7v387WEns4e0CXqblC2u2Iq6FmwAzVuRlVYDEx3j2uWiLtBLWWK
jCubbrVVifUJz9xYkmjc+r3T9Cybkokpd5ZMvWHygRepIb53vKQrpOIRm5Bp1Z+1UkrvvqOA
5ypWTCKQ3rcBzNJxpRqjFZYl+24C9atZ0bo8qEJ+TtNpbNpc1ZnvjzLYQjg7bP4Wdz/Th9CS
cAX7Vg7sXlUnKRP4+U7s7rqd1gdOhHWzUQ2FLTO49p3Y3brOOq7rAru9btdBJ8ITu0A+yEjZ
XUEV9Cyogqz0WqsLLa7gWGZctETa3aeyzrGJEhwXtqzsfxhWfFhWt7tvhZpl4/eGJGfunRWW
divuDefb4L4/nrQfz9hE3Y60NleNlCNqGj2RXRJnPKrbTdKpNWuh5qxq9t8PKu1WNEXK7XDI
5zwdX8KdjRBbE3AQ6V23+8ZWhJZ6Qa0ID+xehaeJBLeCC+zuup3AlbEDu7tyx2gE5wu6vW5n
aGHswG79fCUnA9sCDuhXn8peIRX0LKSCfGVqEoZG/m9Hve6WFO70ls3HJBuXNjVMFaOaoh11
sVzDpt2eY35OsylNXeBJK1VKh+P7lsghHqi7K6LiEZso3PXW2O9NqVa21u2G4m6STdVq1DXG
cM3A/pEddbtJOs1inr+6sONGYL9dDJb8juJOYHH3pIEc+05XdGd9YxO+3MH33IndfVAcgU7o
QXFgtwtOwb2vA7v1/vp3Uhls9TyxW7+/ygk1gzqgewWnhXcGvB0L7BLJORACV34GPczPoBK5
W7m6HkDHeBcZX9878M2RKamYr8cunWP7C3bdlyUub5HFdi8Dptj4Q10iWzliZwq69Y+LVoga
undnoSs84xEbF49aKftbuDNnNEVnlQXfrZ/JxyQdStGPwFp8RyAMhviGCcpXK87Jm9NCQEth
4poVjK4Mnfo7Ks5/lAdfB+0jT+z2mmJBx1AP7G6J19BTxRO7V+LFaCnus8zbfZZ7ChMR1Kol
sFs/n7I/86BF5Qu65Mx4MFt5BWjQswCN0jVmEXN+2b2hGu+rrVrm2ITrSgg8X6eitIgtvKus
WnjQfz/FRuIgpFsXLqIFPJWUJWzGGu/Kz3jEJjSeP2eVnZF2Ag/0V2m828zoj0k6lGI4Knd/
b+fMcFIirzgypjzYTkzenG5SqQgbF9fhaDfg3FvtrfF+AQ8+Q+t3J3a3uIvDFFScBHa7uBPw
+zuxe8Xda/waFHcHdm/9ribfGYPP34HdK+5c4lSwqnJil1Tw7kM06EpqoIchGqVls0KRtQr+
oNYk4B6JX3dr7hSbkrRzdJ4ZR9ELdeLTFS2BtQ/qKlNsJIVrRtYmJWcDreviohUKog42EldQ
wyM2OfrGc2Phri7v4PA6WRFedy+IPqbp9JolhxMQseJ6aIlNog26TyfZmO8fWKJ9xFoFqzp+
1dukZZW8+ylOfDHkA770T+xelWeJFR38OLB7VV5NSmgJ78DuVnmNwRLZid2r8iKeDexUO7F7
VV5LpYHP34ldUsQbtAZeUQ30NEaDMnP1J5AzHJKkC5Ze0tu85Y9JNiVxz2zkYiLnrKhD8ZrB
D7n3W55jI65wWhHjUhsZXMRb412XBzO9V1LDIzb51YpSzGUeW2mwd90SlXdvUPwxTadz7znc
iallhp0F5xyK/0TnPqn8c5pOjRzn7tsjf1Vl8M0WV71l3t8e/NjuxUcFjJF8QfcKO3+BVYEz
cAO7V9hpUvDs7oBuvbfUUq5omP2B3frtSU2iYOPxid29rVAFZfuJXVG8s8Fie0U10LMYDdJI
EjNT7q2iR0xr5nl5IOum2HCSXsJponbXdmBAMS8ZGaXW7+7N5/S9qZl9ofUb47oBttGpS6xa
RvO8V1DDIzaveV6Xp9JaCzdv1Lju6+d5J+m07M+a9CrZiRnsbbJigkV0UCiepBNOjyT+CqA4
pkWz6+aGFN+y7hfw4bNUwG38Ad27vpZUwIaHA7r7aJYzGOB2Yneru6rgWv6C7tV2ricF7Ao8
sXufve7vdtTn7cB+sbbjK6CBn7nmk9ZSK+UmtcDhGYu03f1p2Rwbl2nFOrdSem0G2vjykoZ3
aoOD2dl703yt9fviSovEsH53WjJbQb3ftwDwlc/wiE1M8zoJ32MXf84KWDTY4LE8S6dRK+qq
u0uXQiidFQ0uLO0+PWOWjhVi/9lojdYG0CMjrnpru7+t7bbb8JHgNnyB3V20i14htGgX2O1F
uyoPbPhku7BjeCU/sNvLdmBN9oDuLtpVQcd5DuwSYXffB8VXQAM/Dc9w0VAq114ymqayKDxj
ULSbYxP1N9eoHF6xhUGftzWOxC7s7nPmZ+9NdSXfc1PWphUVdivsKF1K3kmHP560H8/YRPlN
/fZw3BvN4J5yh7CbpBNmxKWJ0/F/PTxluqZmN9B1k2xc0IUZUAs72FrQo9h3zW6FrvtZ2Rng
OcAB3V2zM9RC7sTurtoJuLwc0N3SrhX8RDawu6VdF7DmeWL3fr6cakeT0Q7sV1ftroAGfpid
ocauiLRbE3hadlHVbrDiTrHhaNlnC21XXT9gvVy8pJfLxd1gxZ28N611USuNqFfQtc4vWnG+
3G9rkH88aT+esQmZljvXkiVrq2AT7Q5xN0mnZeuFq2UlZ7RV3N0el39OszFVyhKxddzBwCe/
6Lcclv0SCz7Y33RFx/i3NuEDfXdP7O6Com994IJiYLdrTgVnoU7s1vvrOlzRvOATu/X7q5qK
CXZ/T+zWz1dcq6Czbid2heqk+5RUvrIj+FmuR+m9a6X+iluAffhWFOFGQ7xzbHxzSepfkrK6
HCDQJTEtsUhsA3O0OTactLugoazZaoHzeFd0dfBrNmb8pP14xiY8WkQaafF/gok9cc0SzTmo
XU+RoWg4jX4EYpHCaIvmF/c0fk7fmnB81uLbgmIk8OTNXLbwry46/0kufA3slT6g2zsBCVxh
T+xuhdfQr+/E7lV4msLJHbW5CexehSe+acVu7wHdq+/8jhW8oSKwS/TdoKp4pUfws2SP0kqn
+JukwckeZUmyx23l6mOSTUlioi6GpEgYz4D6bsXeYOizPMeGU43aqDVzLmgyGE+uug88+PgK
j3jE5uWzLLnFCbg8ODH+apvlOTZhsyytEFNh10Voq8Wa0erRTmLy3jT1LXLOopkNTktub4uW
Rfpu79LfoucHq4Mf0N3CTtFexRO7XdihOUsndq+wC7cacETmBd367bWX7wH27Z3YvcJOfQFF
K0MHdoF4kNsFypfbK6SBH+ZnqKvOCMdtgh6w+kUrpJDetqp/TLLx7WUWKq8+dang/HdctOKA
deCVMcfGNRpV34+SqWkFa128qhdwUCK+MhoesQn3PSnNuGsu5HzQAd4VdEbue7N0erde4xyf
uKNnXJTyitNvue3U/Jymoya9kbpSzUXAyc48+SJ4a7tfxX7PH0gFz8dO7F6Rp2FiACdABHav
yKtJCzjreWJ3izzNaNjngd1bvetJCawuntitn0/9DafgwMyJXVK/G/RqXTkN/CwKQCOQt3bz
BZhw+72vzkmbYxO7OXG1yrkVbmAfflljJlhHVZUpNpzay0bQ/9GLENrjuKJ/d2iyzFdMwyM2
h8myVtNcJWZGfxWT5Vk6LoriSSuvXBDYr66vuDs8knmTdIzFukSWXUwZoTJvrrXhLfN+sv2e
gJvGE7tX2kW4OKhMXtC9wk6ToSYjJ9Y/1v8BAAD//+xdUZbtpq6cEQtJSMAE+qN7/vN50rbd
Hy/LpMyl6ZNk5ybn5qPIsjbYFEKq2je7TiYrodfGB3br7yc1+X4Gt3sEdvfBIqN1ny/okuzd
oL/y8mfgZ94Z5Lut5KKt5QpLvK1o7CLju9Kuz8lo/C0np6i1ZMvUQbcJH7Sk7K7e5bu+pufG
ctRrlhDRMbQzywetyEXeigl+r7SPZ9E4QWvSWq+ta8MlTVboG4x7PSajaZG4M2FqJWc4F7lE
oSXXQeHdZDhaxM/uoj0Xxn3r5vQJ3qzuj1Dfsw7mTU7s3u1VUi24unJgd1/OEqpkdGL30ruW
FO2oO7F76V1L1kB56hO7d/3VxA015zuwS/J2A4J3WTPwM9sMKlabE6Kaa4M7RmmFap3xXW7o
czIaTi/1XidEvRij3n9r9JX7wJB0dm4sijas1szykl3DCN6SvN1tz8v3Svt4Fk1ItdTK4qGw
k1bwLLGsm3dQ4jkZTuOmlIlZxf9G6wjbEtuMeq/lPRuOhkMLadUenilod/Jbq2UBw9uuwYfW
4RzQ3Vk7gxs+D+zuvJ2+VLlABb62IlH/LG/XtcAXxoHdnberqMLiid2etzO0h/HAriB2t6p1
vt1e5gz81DiDaqaqUgnNRC4jdoOG2aloIgknhWoLjdgMelStyty1AbGbnBun2y3k8JpPUEez
qrZCCWRknMGXNcOjaCIJ15s0P0aEJhDcMruoyXSQJJ4Mp0Ujbu5CJTQF0XB+PnU3GY6Wwtx7
9a2oF0Z56jt1t4LY/ZIIX0E/+Cd27w5bnFSi1lQHdnfqTtBO+Rd0L7/rCTWOOqC703bVCLyV
PbC703bVwHu/F3TFrSzdS1TIZc4gD40zzLkDda5Bijabot2lHj4nownVmWJVapWwN8UyDzFo
BbcbmKLNzo2T7pCZerVkolLtS0zRhhJ8clkzPIom0m9RLernk2Jk4Ll3gwTfbDiNqnG4opEU
AysAFnG7UdJuNpyQ8M61Vmu+3OBSyLlWuz+d2/FPiPChZgG7bxdBerLgo7KAB/+WMKAwxjJP
7O4LbAV37gO6nwODvOIF3XvC8Q2mgHvRid3665mGYgb2fCd27/P5wQDsuz+gKzKcA6E2uZws
5JkvR4iRVFX/s0tHeeMayZjbSsvPyWj8E8SNNARwwmoEFNH379aCaOpAiHo2GpbsBK4Lmaqg
fdIrztJMg9pEuYwsHkWTU42+4tDUNqUKfrZ91BJRwHYvCjgXDqXo0JLoKZaeQb8hH7Qmwfm3
S+15NLVFMGytv+QgsWjeF9ereN0vaQJWxj75B3T3JaKfy2BNu8Dupnc9g5fsJ3YvwZPUUFXl
E7uXQIXQH+g1cmK3Pl+TlMEi7QO6Is1Z7q+w5XKzkGfeHNqdu5vTY2Oc4K0QEiLVwa47FY0k
Jw+t5FB9Rtm3j1mR5aztvqV4LpiSeoiSkHJvobkC8ru+5Ab7Ni34vdA+nkUTzhwUStzSqOeu
sDXHiiwnD26w58KJTL/TOyWtll9G19uuBzjzvWHhbDRBuVvzT0FluGMy6buheBG/29uYULtv
59gkH9DdxM4qWBJyYncTu1ZxYhfYvcQuzvjgpdiJ3fr71ZwKgTn/E7v3+VoqqCbliV1C7e5F
eOWyjJBnlhG+L2X/ovvJrBGoEsFrDDB0UJ04F01JVDnEb/yfrKDASlnjd9zzfcXYbDSh8qxm
ktUI/Nj5oBXJLhrdYF+eEY+iCc0kabV2cQKhipvQrjH0uG87mQ0nBPqb9uxU1Wke2om7Rsxn
0OI0G05v0U9cufm/FPCMN6t+82Z3f4oqYMYvyE7sXppnyRrq6XFg99K8mrSiNf0Hdi/NC+oB
qtqd2N0XoEVBmnxi9+bv/DepoKLHiV1xRXurBuab7+UcIQ+dI3z39c2qi3RCxcDTEjGc163j
3d47FY2krlTCGKw27qD7VAxaUah4myX6moxGUxZxfte1l8zgYtMlF85O8+5lxuVyjngUTRS1
eSTcS5XOoFhyXiKGM2Z5k9E4w2tmzlipNNQjwUctSeG1v11qD8Oh5KtMjCvnzAzu+5RoanLe
JO83NQE1taywa0Fg9xI7jstCWBQwsHuJnSaDX5ADu3V+oxSRwe7dE7v19xNfU2Dt1AHd/XQd
PVac2BW07lZHzzfbyzdCHnp6+ItbSISsCCizskzs+d5Cay4aTtxZtRhTtJOiJHVFzSv1PNhr
J6ORzNap5pCea3A3zQoiRLelat8r7eNZNE7rSEonj6c7EULbT1astHH7yWQ00fVduUbHhjD4
oZr1r4XD+fofwvHjXe45RAErWAXgo/6V7Sf/FVVA1Ov2xO6ld8UpG+hP+YLuvpxl9D7lxO4l
d+rbANgc+4LuJk8G3g8c0K1PVzgVA5nQiV1xMTuwa5PLK0Ie+nj4W1urf9apowZni+zaXoaf
dxvuVDTO0jLn7C86+T9o47cPWlJ0d5d//JqOxqi3UrirmnWUqK64NB8Ik3yvtI9n0YTECHdR
J6lCD9jDnDDJE243GU41rb07w2tNK5hjyEsKPKNt/u/W2uNwOsVfrYqzbwYFsfJkheeb2/2u
HiB6FDmgeymdpMygnt2J3Z2x89ce9vEI7O6MHRlY9XJi92fswN/vxO59Pku5g5vTiV2Rs6NB
D+PlFiHP3CJKs1ZDAqy0WtCcXVmR5bLbovDPyWgi/Ra+WTlL9v9D6wdXZLmo3uZTv6ajEap+
2uMeQs+gMjIvMq697f39Xmkfz6Jxipb94B93l60bg0stRv00sZsMx09DJLVTE/XpgbNcP560
mw2nveSJmp8hlEC5pdlw3sTuj9AD5Ao2K57YvQxPEymo5nFid6ftBLWQPbG703bhnIT+foHd
zfCq4beegd2dumMDrUZO7AqGZ4Nb2csuQp7ZRWiTUoWNwyEVtuBdoofCg213KhpO1EnVP0Ya
fX9gUt8HLSm2G/TLTkajPUvUumv4taHRrGhl5lwHt7KXWcSjaCIJZ5G9I2FW1EhvWU/F3y61
x+FUteKBRCqyMSyRvKJMdZy6mwyn9ZJbdM1LzgyrArZ/5bWs/IQqIFo6vqJ8Z1mnx2b9PUmt
MHb2O7G7r4qpoJVsB3Y76xTUx+PAbp1faSmDHR4HdOuvVzl19PFO7F7O2VMv6JnswC74lHC5
22ucCVxOFvLMl8OpZo8G4cgngBZlPmiJP/CtGd7nZDQlFd8yWSo7EyC0jNkHrcgq3na+fk1G
I+HdZJ1rbZargVWxacV3jokGHeOXj8WjaJxuZePScw41atwguK4pBRwksKfCoSRaci5NiQlN
Ksagn6ack5Pjy8w0DjfW/XOAMug+9R340ynnf0mEr4FGHgd0d14xdzwvFtjdDK+BZkkHdC+/
66kJaBB8Yrf+euasKBfsu3litz6fRiYdLPY8sSsKAst9mVa5/CzKQ3cOy61Rl6JmBPcTLGnh
HSi1zEUTBzlhIWndOR6sbbKkD6fn+213LhpJ0ot0ydUZa20YJZI1xmuc77OK5XKzeBRNDplW
E+dDpmwCZuR91IqO5Htd4s/JcEKXWEqpOVvX1lBnbV5SD6j3Ksuz0WR/cVpwcJEGVjfGoDfB
W0Pw9gp4tJCDBN/AE7ub2xWwZvGAbmd2YMXsAd1bD5CTgnccB3Rv5q6mImDq5cTu5XWaFPXB
OrFLeN39bXG5HBrKQ/eMXAprZakV1ZrhJcZe9NL5uttsp6IpSbt0jsKz5uwBY0JljVR0kzsm
9DUZjSTuYYiXzTp10G5C1vTw8q3G2/dK+3gWTU6ld6d1qlmJ0MlZVA8ot/KIn9PhdJXe2SKx
ikpX5iUqQEx6byE3G421Yv59iT7rOBahwjnvcsBVxO6XBPiYwa6AE7uX30X7K5hreEH38rua
VNG72QO7l+FRMrQi8MTu5XhOyQuYWzyxe3OL4jwHrA04sUs43v3tbLlcGsozAw0JazQuxp0M
7ytYoUust/mhz8loirOiqtqtUMsVLDora3o+2mjjnYpGQh1Bm9OtWpxPgA1QaYVkAVMbZIkv
k4ZH0YTkSs++ylgkd8KFWpb0Jg+UHmfD6SWHSXDT1kXBQo0Y9aMFjl/T4dSYnBz5yObv0Fuo
ZadQy96t31Iu4PH3Bd1L63yzRIsdTuxeYqf+gQXLxk7s1tllJ2sK7hUnduvvJzWxgYaSJ3bv
+mspFEix3+/ALiF2d+ku324vi4byRDafkrSQzK8qoQ+LFg+t6eUdbLZTwTjhfHUmt/DxJJDX
8Zpoer6bmq/pqanBGApVVkZlQGhyq/0Lr7uXAyqXP8OjaHIq9bj401yMYGe0skbVZJC7mwyn
5bCK7lVCxhv0mfJRK1g32yBPPBmO5ThBSNPKhFbb58lDxJvX/RkCfBX1zzqwezdYP28beHt3
YnffzNKDojvaXXXHnKyDmbETu5fgOSmqDBK8A7v3+Sj6r8HnO7BLCN69Wku5zBnKM8X8ksn5
Xe1aW2e0eGjJ7azxoBRqKhona8o5+8su/kXC1VpWGGf0PMjcTc5NF2dFVDqrVLAzmSZr3f9y
OzvI3F3eDI+iyaELRL13M62m4N6SlwgDjRneZDiNNBpEwvWNQEFOH7QiD3nvgP01HY3V3Fvx
j0CuZPDk2BT9fhO831XhKySwtHJgt6fuOuhMcWJ3p+4UrVg8sbtTdw0VsD+x21N3HVx/J3bv
+qupK6gldmJXMLtbtwnfby9/hvLMO6NkLb4zae6aQXEGH7TEO4MHd7JT0UQaTqN35fx7ZxXh
MHc3OTfOt4uz+bgzb+Bu6+/qGu+Mv11pH8+iiSwclUhzlVDQgWVNfj53NxlOy+JvTGZmNQWl
yfOa2Sk0uJOdDMdyeEb7a+MEXME7u1nHuje1+wN0+MzPJmBV0Yndnbvz1wpWRAns7tydZFB5
58TuZXiSCNUpe0F38zs/4YOCLQd27/NF3RmoUfGCLmF399q35bJoKM/sM5zaKXNtYeAJ0mkf
tIKrKg1uZqeiCcHksCH1N6lpBQ1vQ8x4Cbu710OZnZvuU9MLUbVSwQ+dD1rTLTvo37kMGh5F
Exm4QiUzGTmDAN1AduTtJsNpuZg09u9Opw5aRS9id2R3PS9f0+F4FFoLxS6kBju92b+y4u5H
NPgIvCajFVdk/1gVvpJyA/s8TuzurCK1ChcEBnY75wSlpg7o1tkVTcqgBsqJ3frrVfMVhfZ5
HNitz1dKUgGVvU/sktviO2bjXODyjyjP/CMobopFuXEXsF/UB62IZtjLOxWNHy19zwzTtrjB
AxvVfcyCYOqICExOTZXsC8eqdKcB4JdujaYJ3wrOfC+0j2fROEFRa2JxnV+pF1RaeMXkOOm8
m5zPyXAiF2+1cFbNlOFazRW5+HCa/rul9nhyGktp1nsp+VAM+MG77z+dc/53RPg0+eKFBSkC
u70kUA1OKwZ2N8VroE36Ad1L8QxvRT2xeymeJLjM5sRufT7NSdCX4wVdQfB4IKFx2UeUh2YY
qs7w/Hwm/nVHC+hoiQjfrTDx52Q0JdqSGxMVyWwgJypr2pIbDS6NJ+emV5+TzqRcO6gH4oNW
2IPx7RX490r7eBZNcDUKDV99ifF1OHG1huHdyyzPhUNJCvk3W7tILaAucQxaEs1A73FycjoV
JRJh4UxwzvdtyruK4W1W4cuJDdTxOLHbb4zhdsoDu53agQaHB3RvPYBvAh28kT2xW3+9Rik3
UCL3xO7N3rXEaC/PiV2SvRvUaV0+DeWZh4YqFw51NOcR4Nu0xEuL7Fa67nMymOIUPyRAtNVC
BTz2lSUNllQHtm2zU9PMnDyE07CwoeLXbUUFHd82rnwvtI9n0eSk0ZmsQR44v0raMJGWFWyI
bnUFPyfDochlUG4elJ+4cEniFdm7YT3g5ORYJjX/SPVcfbGh5Y3vesBl3O5XhPii+KeBQnwH
di/F01QZJAEndi/Fq0kzKMd7YveSvKDl4LfpxO7N3/VEsNzygd2bv5PUwdfjgC7gEaz392Z6
GTXoMxMN7t3ZkDYneDWj9q9LpOtGNmlz0ZQQeystn3+iJhorVs7QJm0uGvGTi4Q0WtRsErjW
YtAPlwXq5dPwKJpXWWAI+nYPpSlY+rOoLHDE8WbDCRE+qU08lJYrqj/T1zDw+1zxbDhm3I1r
70wdFXqYza6+Sd4vC/F1NDtxYPcSO07+fQCJ3YHdS+w0LNPBQ92B3Tq/TIkKaptwYLf+flJD
9BPu5w3s7oNF66iU4YFdkb27LVz3DffyatAnAvrhyWm+OZXuS5BgpZYl/mg28Eebi4bDK8dZ
NPfauIEZIl7Tv9LzXWb1a3puzIhLqyJUG6hLSYvuMgcOuHpZNTyKxkmattpqbsXCjw+9ml1R
9Dvs+JgNp4W3SSNTI0WTq6ukWgZ3s7PheBhNWusWCoOwycmb2S1gdr/UztsreL46sXs3WEnW
wOPsid19OUtgeckB3UvvQqQCVIA4sXvpXUtgK/QLuXflNac3oC/0iV1SdXdfC6WXRYM+kc0P
lWXR0orvt9rB3EMMWkLt7pt556J5ySyz/4fNuME9IotUlu/tSGenpip1LT477OwBreuqK0y4
+LYz+XuhfTyLJjRXnDWYVHGWah1WWV6Rg7xvRPicDqcxa9WacwsFUDTLtYbZtfsWntlwLIvT
bc5GFVaPfd/M/jNF+LKB7agndnfSTjsq0XJgdyftLD/wz8j7/TMaat56Yncn7Rrc7XFg964/
J+Jopc2JXVJyd18JpZdJgz4zaSiZ/OW14psuej2/TF55kLSbiibyb1zJaVCX0uAOhCVJuzrQ
vJ2dG6shWUcSVvNoPnVO8fb/UyEd5Owuh4ZHwQSzK1XC2STqd+F2ikUafANmNxlO8x+p+BsT
7K42tP93kbzyfcfsbDhq1opyKY0KwR2z+pZXXsDsfiVpVxM1kKCc2L0bbElZwX7FE7s7aScE
duyd2N1pu4qq0L6gu5N2OL1rv0DvesqtgceLA7uE3g0Sd5dDgz5zaPDzerThUjYh0OVpmT/a
HVn9nIwm1A5b4Vz8OJdFYfeMFWnITgN6Nzk3zoV85fToRBDwniwGrahPa4PCzsug4VE0kYMj
a9SyFW4Gq/j+fOZuMpzGzrN6jblBayEX0TvWv11qj6MxMiWiSiU8idG0qv0rBVH4Hy/C94in
gBRlwTdyARn+NWlAsCbmxO6+v1ZUPO7EbqfCYEWRLREUeDC3/s1LxOi7eYK3/nrWEmVQN+bE
7p3dTClKzrFf8AQv+JgwDwoUL1MLfWI0YK9zhOWupRKqQGdLhHVJR7nOqWhKetGtVl6SK2B9
qw9aoR1T7d5KbnZumI44ip9UwBK4GLSCDN/a/H2vtI9n0XDKWrTlSEIr6GwTY1YEQ4NT11Qw
lFg7O3MsrbSKFqKnFfkiznVQCTsZTau1+PmxiLKAN5zhQvVvZML/HWnAkqyDPR4ndi/F05eB
NdoDYNtJgKWuoJvsid1L87gmK6CA8QXeTfOygArVJ3br8/WSuoGuhid2ScZzsPVe3hb6xG+g
JuXqey73bMxg3aoPWuGiojJoMJ6Kxk+bxLl1our7Fbh8yhJlD2qjzoCpaOLDlVkrRQ8YWHip
k9VjfylVvBcr0svY4lEwnESkZfaQtAtaXu6DfprkTUXjfK1Ia0bRV15RqbC0wtSc6VbO+ms6
mirGVTK1qDlA7QvnNq03yfttdcDaE6M2Rid2O7szMEV2YnezO7CA5YXczOwsZdQO+gJv/fUq
p04gNz6xe5ldD1MM7PlO7Ir03UjQ4zKQ0Ceq/jUV6+Ee4Q9YS8MuGOuSAjKygePCXDQlidPT
2G79MFdBv78YtCJ9Vwf1Y1PRqH8WWg9eEn7OYDQ6mVX5C33425X28SwaStp6NExHRSwTWnmp
awzlBu1OU9GE6nFvWriGiXctsFbyirvse6b6NT05rERcjFvLsCWVD3pzu0Xc7lfUAUN8E0zg
ndi9FM9SlNCj/QCB3Uvxqn+eCGRRB3YvzSviOzWawDvBe2meJKmgKPGJ3XxPK4kbmMG7wCtS
eLfVSr79Xj4S+kTcvyVS812dKJdewe23LfL4GN3TTkUTV66U2apSzQ3UiF91TzsielPRBNEj
8Y1XRCtnNIe3RAc63za0fq+0j2fRRDVlKCH5IlPJGdRgWFOCOSR6U9EE0cvdOpeivaEG8bOm
GH+5qR10tk9ODjf2deYHvtYFLbVPc+U7b6L3uwqB3DvcbBzYveQusjZoAd6B3bv1azJGyd2B
3Tu/mhj8Gh3Qrb+eWJIHxnKyuxeltHCSAL15D+yK/N2thYRvtpeFhD60kOhVTXxvMhWC7cHW
tBoPRNsmoxH/iarUXktjVONnTf6u3UbzNRmNpFAHzEJarBjYOB2DVqSIbrWSv1fax7NoQvW4
moSjXhxP4HaHJU50Q33AyXBqK1lqJv+roW1peRFN1QGvmwqHojhSMrdSemmoY8FkdeSb1/0R
+oChCInSu8DupXfFdybQieAF3X05ywVMG5zYvaWVnPy8iX2TTuxuehdmTyi9C+xeemepo+T4
BV1B7sr9lmuXd4Q9845gdnpHpZSqChaJ+6AVZXc22HHnomF/jXrhItKzVVB6hSfvmP5/zm7g
3TYbjX+znN0xhc4w2CkSg5bU3d0XeNrlHPEommjRig4Rad20gNuKD1pRdzfidnPRvLidmb86
Vaug29AibnfPvL+mJyfnZn4oalFxCatRztWrvrnd7woE9oaTusDuJXWSMlj0dEB3Z+wUFQY+
sbtnF625O6B7KV1NFRQhPqBbn05DtAz08zixP5yvs8szwp45YHQTot4tKtRAk4UYtCRfd38N
OxtN4ZDR09yFULNpH7SCoPZbB4yvyWjkdc7LGplURb1WZFG5/iBfZ5djxKNoIvNGr67sIrVV
kDZsyNfNhtNyyeIHIWlNCqHhrGg0H+br5sKh2B1LIe3M1VA9ER/05nT/O6f7JWlAQZ1uT+xe
aqeJCnhdfGJ3Z+xEUO3nA7s3Y2dJwUK2A7qX3PUUvp3YjnZgd9M7P9jC9C6wCygE9fsqO7uM
I+yJmL+kYqFqp7FRge0/ssRCi2wg1zYXzJFXjutlCr1D7Gzgg1Yk7Drd38bOTg2RdGsS7hGC
0YcYs6TG7l51xy7TiEfBUApz5JabhBAlKIYSg5Zwu7tD0edkNP5ChyB3YarKLCDzjlE/ze0m
J8e5XXWWqlatg6KN/1ZuJz+hCwhe7Sy51lnW4rFdf49QB+gTu/t+mMxAvnlgt/PNAus8vrBb
57fVFHdPWBn/gd36+1WnNaDB6wHd+3Q1FB3BxzuwCz4lMjCAsMvNwp5YDKgfFKMFIlpeG9i2
p0vkMsjoXpdlLpiSSmeRpiGo20Dt5hi04oK4DrKJk9E4CVCutZFHBLLnssZDbtS9a5eXxaNo
KFlWD0V9nZUMVsv5oCX0We5kZj6nowndn1Ja9zmqcPZNVsxNHgizzEZThLRbrp2agPZ+NJmF
/9P55n9Jfa+A/sAHdHs6kVH9pgO7m961B/Ism/VZuqZaGVQXObB76ZOfVhv4fCd26/O1hisr
ntglBYCD2+LLzcKeWAxoskpiTXMTzhnldyvcykhvbyQ/J6MpiXPnXv2PEi0eICNaIUdM1e6b
dmfnhq22LNF7IwxG44NWNO3ei7t9r7SPZ9GEeXHPvbMTPLiPyAct0SPWAb+bjEayBmG1nAuu
rixLhK9vuffXdDQm4u9MNQuvP7T+z978bhG/2y6852Qe1Fg9sLupXcngXeKJ3U7tHtwUt903
xb2mxqgo8IHdS+5akgJS9xO7l9z1cHbGuN0LuoLa2YDaXd4M9kQyX1Mjshb+oM5NwOUQgxZE
U/qgEHAqmpJMi4YbXs/hzgBSO1vS2zGidpNzIyzE3FtVMViPZUUbMuc2qEm4zBkeRUPJIwk/
6lKkEygjSEu6iAZljZ+T0USB4ivdpVxyzmDF0qKyxvvGm6/pySFW603D+FhAv6zZxps3t/tT
hPc4EaF72IHdS/HMj+ogBT2xeyleeAuA5WInduv8UtYUtdegbNwB3kvywuYJNXI4sHtnOOeQ
JAWn+AQvyeHdWxrY5c9gz/wZeq9Vcu2V/d9Qg7S8xCCtD0q1pqIpzvdVSq7MziIbRo3Kkpsz
qnpHW7+m56aSNjFlo4ZWOPqgJUTvVtvte6V9PIsmZNrCBaR3LkoGi/j+tPDeXDShldyodYqW
ZGd6aFFgX9KTfMvCv+Ynx9mjRGOa+hcf9gL5V5oF/9uF97KB1p4ndi+5Cx1d7MN9QPdu/JoM
vX54QbfOrWhS8Lc7oFt/O6mpCFhTeWL3Pl9LrRgoY3JgV1A6HRRDXcYM9kQtnxPX1nJ4GfjJ
DKT5vGSjJeO7nelzOppw/2jSeigQG/hlSGUFQW1lkLubjCb6Iixyqj0aLNFo1nRGDPo8Ll+G
R9HkqO0Qa07qLHtAsErdEmnoURPvZDiN2HrhTkq+6LBPQV6S9R70rXzNh1OEfVZMoga3YNvW
bN/Km9T9Gap7Cp7hT+xebudHbVDE44Duvpklg4vuaEUZ0xNu1/3siGraHdjd7E4zmPQ8sVuf
r5REqD7+iV3AIGjE7i43Bnsike9kwD/m3bfdStHAhzKINZZogzTKZDTCmXILATEpFVXdW2OJ
ZoNS98loKjeqxeelUUZPsamu0akb1ABcZgyPoolG9lqtamNlQp2OfNSSqrsRu5sNJ6splV5y
CEVjKZBl7O7uzfmaDqeXGkJA8qryZFjw+q2p/L+zu826e5oMla86sbtTdiqoxuiB3Z20UxXw
su7A7qV25nMG0vYTu5vaRQIGFt9rm29jne6+NCwwZuzQBeRBdJBMufwY7KG7hIZqRmX2bbej
5GGFqaATu0HJ3WQ0hbvvsiXaMQkWIF6ivVdtcD02GU0o7vmG24uVDOsi6hrq8Lcr7eNZNMGE
xDl3iCOyLzeY2C0Rqxvps8yG42xOmznJ0kJgBt9H/Szt/poPR9UDkhIXsgKq58zS7jex+yPE
9wqBRckv6O6knYHO6wd0d9KOO1qIdWD3zi0lf5FBYcUDu/vSs2TQZPnE7k3bhb0J2O5xYpew
u/u0Xb0MGeozQwaVqrX5qMyqMINYEY3xvRbKbDS+LxXqftKszUB7+UVcdZS2m43GTyyR63JK
5LMEFhYv0ncbpO3q5cfwKJocdr2tZc7mrAgt9cmL/HoHabvpcHLvfh6yQsUEvKBZlLYbuWXM
htOrStcwuZbWwab52QaRP53d/Yj8HmrbusSy9R8rwCepo/67J3Z3TpEZ9d89sLt5p6A9Mid2
6/w2SRnMIR3Qrb9etVTQLtkTu/X5LNoiQK+WE7uEdd5dEjkXuDwj6hMdf/WZLSGcIWJGoF10
DFoQzaiNdy6aOF3WVp3ONraKetUkW6LAF6Jyd0xgMppcTCmHPFK0ioLRzHmi/n+adnsi+F5p
H8+ioRTOF41CUrgX2AVsxflmoFn3OR1NeF+UTNRyLbhm3c+2WH9NR8PxVybziREwl/Nu7vjn
K/BpBsvtT+z2YkADbz1P7G6G1wxUkTuxexletEhg7/IB3cvwSiJBJYwP7N7naykzWBNwYpcw
vDtO5Pvu5RtRn6j5a6JWutXqu28t6OueVshtD/t356Lx17ybZGpCcXuMcqIlzR4933t6zEZj
XLPGf7loBRtxyqQyGqzz9r3SPp5FExrLJZfCLTsHz6gJr625NL7X4JuNRixnDZPkltEbfVqS
wR5qLM9G49/3UoofRIUJNkh+ayyvYnjbNfhKBanTid1N7RQ1uD+x26mdPtDg080afC3aS1AB
ngO79fdrx4kSe74Du5fcSZKMfdIP6E9Tu8uioT5zzyBirUbZ/+c8AqV2KzT4nITdb7hT0ZQU
fq9WIhWZM9gF5oNW0O5WBymVyWjEWbcqFws3rZ1CM5zbgNpdFg2PogkN9JIbeTwqDdQyiUFL
yNAgTTwbDftSy9EzXhtYahGDlkRz3+cxF00IzUQjPzVVIgE1jWLUm9st4na/osEXKopgXduJ
3UvxXr4O4P3sgd1L8UJXD60LPLBb57dbqgQapJzYvRQvJz+mYs93Yvc+n6SCakCe2AVE4l5h
1bfey6ehPvNpULKayTRMZUHO74NW0KKRR9pcNH6Ws9h4/UCnrTWU5OmK5uSRR9psNNXpN2fr
PXtEqCPIGteJgSlvvXwaHkUT/rrsZDVXNkL7RReZ8o6ElueiiYo4CwWd2iUXAxN4PmqNks69
1OPs5GRuuYQ/WvjpwKa87wTe/97zsV1/r4C5iQO6l9ZxKtZBWndg99K6ENUDW6FP7NbZlRLZ
Qqyb4gXd+utJTQ1tljmxe5+vJHamhv58gV1B6m4t1n2rvRwa6hPZfE5+Ym/ViUM08YGtXbzE
04CMB/mUyWgKW2S7WpbCoEPDqlZeGpTdTUbjNKhSjXK1imqM8xoa5Dzo71bax7NoslNUckZH
3Lp6VGh2aImP77DZYzKc5ichq60X8bkHW3Hykiyx8/wBq5udHfFY/JX0Ix5aAOCD3gJ8C1jd
LwnwNQalKE7sXnonyeCs3YHdfTGL5kAO6F5yZ/5qogLBB3YvfWqJURmZF3Tv0/UkoDP7AV1y
KXtHH3zDvTwZ6hOhfGdpFgVD3Q/p3EEXA17iq0omd9F8TkcjxoWLdM6aQYW3RX28ne7FlWej
KRKaGSWuMQ2U711DVIcqLfWyZHgUjfOAFu6w0jK1XsFTRIz6aWo3GU4jZ0POVbtluHVuFbUb
qLRMh1OcePubo34o6qBy5Vtc+Z8ov+dMg0Ft8xO7O2enaNLpxO7O2amC1YAndi+to9Q7KDFy
YnfTOt/VQPm9A7s7a1fAM8UBXULsBrIZlzNDfebMkNU6NxHfp7SjWa4lGUgbaKLNRlNKq1qY
cmmKU6ElRmg0yKNMRsPklCGcVVkNbC6NQSuuLm/lZr5X2sezaHKyKOmKbh2TjDZJ5SV9zJxv
+0I+p8Np7FSIhWojQVt/l+XsBpf+k+HUUmpvvo371KA98++k3T9afi+Dq/aA7mV3oROAalId
2O0puwYKyZzYveyuJlQ/7oDu5naVsLPjAd36dIVSeDOg4oWBXXIfO5BBuXwZ6kOXiUyUsz+f
wKpHMWjJfewgaTcbTbUw6tRStYEpVR+0Ym7abe/B13Q0ymKx20ovqqPF9n8AAAD//+xdzY40
uY18ohUoUpTEF2hgu59i4dMe1j7svj+WrEo1YA8yv0iNWv31uGx47EOk0VH5oxBFRvyTMeKa
stBF0W6kMtxi4zrAqkamiRAVU9TebZG18oW2m6TjOqiJ5OqPWqRm/DZFu1k6TfwZay5Y/eUB
l4VZa8Tv1Xb30szjX9gS/sQu+JT8ab34P//4+z/+7x9//++//Yf/Uf/xX//7t70N6Fjr+WYt
Bsqw3+H2fY/voUVXoIEnXQO8V/BT9eUAbCIY4L2PWbEEz9U9sVvvMReKEBd0z/QE7xXWFosK
2ihygPduTFSTS0zwvP4AL/is5KsWuZHd0e7kKYQFiXLVrNa1gg45ftGKMerSLpoxp9hI4qZN
siqxMiiXZU24cz+Vyx+TbGIroy4uzZxOB8/Y1mxlorb3qyft7R4bShyGPzlbbr6pQQ/sV5hL
MNPFNnOSjUql5rtx39C0AjtVr7F0LBd9v5N0xPfKj7Hw7LtmRunIVLnvVdf9TVwQLfdwSEP1
3hO8V+9lSdrAqYwB3nyAX1IF+x4P7Ga9Z8kaeI42wJv1XkvU0AjHA7xX79UePwvY2/rALjnG
P/N1+0/tI8uj38lXCOFWuXQRpWa4S90KNqWeH+PPsZE4+LbSupQqDBqSy5KDbxcx51Ymc2xC
uIUC9w2rZQb9u3lyBf6D2jsv9faR5HGLjQu3Fr1e+THdkeHpjhWtwCwXHSOzdLRkqb7PdEHO
ndGGxiUJRXbqJPoxTccVay/+7qh2/wdKZ85K9CX3vtsSMbuuTxUNb/pEb1Z6LRk6QDLAm5We
+uIBzn8P8F6tpzWJgh/bAd76GyprKqC/3YHdq/RaTBqDanmAl2i98zHrPhI0+r1cg6jqxWvM
RRXOnKgrmhzrhSPxHBsJdSSVqpBKz1h9Qpaoo9z62b35mGQTsq2Thd1Mhd2ieYmTt2u9c4PE
PhI0brFx1SY12oNrtepfFDQxeUUkAPOpMfn7NJ3i0ij7HjNHHgiYIhBXLSntnZtxztKJnGRi
169OBvVbiKteWm+R1vuO0p6LuPAoAetSB3iv4OOSfOMOTuY8sJv7BbIvOnDz5hO8V+617F8d
MIVlgPfKvcIpo0/hAO8VfEaJCtjIPsAr+jjLRcllBGr0mxEUnXP0PVpVQ7td0hLrx9LOD9jm
2Lh2U9PIB2ku+8AnSFYNX5/P6Myxce2WXelZzsQRaYcKvhWdgnxaqvx80t7usQnpZlqMpGbX
SbjgW+GrwxduibN0inXfXuSYbutobBQlXRKscxoE+TFNR2KK1ZQla85gPh9NvjovwfeNdola
eqqo0e8A7xVRZql3sJ4ywJv79TjB2WADvFfKV0sVje1+YvcK+SKJGpirNMCbtxq++BDY0T7A
S/r1LmotI1qj34tviCkTV3m5+/u81ac4l1PX5fdpNo24M7kYFpKC1ijbioW3ndYoP6bZ+A6m
KiuVOF7fm/JL5wE7fURr3GLjgoDM1XdrriK6S1dURqyYK3fJ/6tH7TadUsQ/PFSrVlG4w21F
ssD1Ce4sHcoPP+wIp0Gn9l4nuD/XPVHV714F17AB3rvKUo0iHagDDvBmrdfiMwBKvQd2r9Jr
LeWCejwe4M1az8JUFw2mfoI3a72WpKFP4QFecYJ7umT5CjwSNvq92AOmXHKMYlLujEZ18Qp1
dKn1JtlUk941wo4I7ejNS3xdrrXeJJuwD4pgbimuj1Advkjrnc9m9BGwcYuNqzbOrlhJ1O+8
gf0ZcdUKOno+mD1Lp2iYKRYupfizhsafrDB4cjrnwxnTdLKQb/mkSq4VHp0pU0r8pfW+0U0x
dJtlsPl3gDeLvAjWAeOBB3h7QY8Lev51gLcX9BSMuTmwm0UeJ2uoE8wB3l7Qowbbej7BS0Te
xdI7Ejf6nRSEqM3lqlp93WgC5ocsKujV06LR+zSbRp2jd6p1RbeCftGKkYxLkTfJRkvLxlaK
xSQDKvKWyIirgt7I27jFJgp60W4oVJ0RgzdnUUGPTgPA36fplBL+nQ8yuYItoWsKepyvTm1n
745ZCTehHGbzghpFvgp6K0Te9xT0ij+MYMrtAG/WepY6g703A7xZ6/XUCzqScYD3ar0efS/o
5M0B3nuXlf3GoYM3B3jvXyixCmFDagd2ida76NAbERz9TixCThxGi6X6Bz5CONCC3hKzlauC
3iSbal2FpVRiA6sSOw5vJ9m41vPFtyj1hjZNrdJ65ULrjQCOW2yiNKdOxrWRWgfrCX7RirCX
bBcNepNsiqqZZXO5ZxUuT67wqriu583SyVooF99NUhGwsE+T3aC/u9QTWOrdWDHAQI0VWRo/
2esvK9j3NsB7l/3cEppdfmA3i09LtYKjAwO89R7zIwcYnQc+wFt/w9J9DSUwl2+At/6FErsG
Ad0IB3iF/DyVOC4KRlBIvxPe4D9e1VwtskKIMDnt16zQ0q6tzjXBFJnwcXG9JpxdTBNYN/WL
Vtwau8hdnmPDLr38rphS4Y7GJi5Ra3w66/L5mL3d4xJbWLXKZEW0wtMUS4z+zuvz79NslP2z
3VrV2B3AYm2FqyvTqd/nxzSdmJ5vIaMrWwXP8WjSVPJ3157/RkZ/LTUGwyoGeHONR5IxalN3
gPfKPS2+GIJvzABvlns9VdhC5wBvlns1aSlgaMoB3iv3wq25gMMsA7xAU+R8IfdGdki/k+cQ
FS1xsZdD7zXYAGaJZdml2d8UG0kxZNx6jm5IEzAVyDetK/Qenee6zLGJ+BxupYtGUA2oxddk
7rjiO4/97iM55BabEG9EvqeI6GIRuN9ukeS7KGxP0lGhXHNX32HEKP1WyXfh7TxLR3rrvm8O
l0yq4FzSy9v5R5v9NXhgdKA3qz1OHY09HuDNak8To8HHA7xX7RUXHw0sFjyxW39BzTlyL7D2
hid2r9Kr5JoCFHpP7AqdVy9GgkdMRL8X4aFdeqVipFnAw7G4aIXOu4jwmGMj/iJVMe0uq58/
Fub7suRUmS903hQbl2yuHhv1OIRt4Kkyr5mr4HyeAt5HSsQtNq7YuFql3Pxb1wpoiB72gCuO
lfuFp+QkHacgLqashkUmuG+Oq5b0d17ovEk6IvzIAO+tKhXU1HmujPzSeb+P0V9PDT1C+0Tv
lXuPYzFQ7T2xe8VeuPcR6gFzgPeKvej/BGs4B3az2AtDblDrBXSz1LPIikC13hO8ROyduzrb
SImwewke2lrptRKRMhg5u0rsXRT15tjEIS4ZudxTbeCGdVmAx7klxxwZTtxdSxTfqbYI1QO1
Hq8J8DivHtuIiLjFJlSbNNZWzPUEwRZ/S2pgen6KO8smUi7E90nGlTrouL3K0/nUovpjmo6I
ZSFRa/4P+BD3Zen852dFvsHhT8CVa4A3d+nl1ED1eWA3d+lxqgxarg7wXgVfa2qG9hEe4M3l
WvMvDvidGeBv6BUFnTAHeInCOzfXtZENYfdyO1w1lppdwVM1sHfTL1rRplf6xcI7ySbObH23
VEtvGawYLTKltlNR9DHNRlmtKlVtMRGMqu8l9a92IfFGMsQtNjEQXCizi7xo1ANPY2jNKTTx
eeV4lk6R6h+fyOSN7Dm4nLcmkvfszfmYvztWa+++mxBuaCDgayD4Jzv85YRO2x7YvWss92QE
btMHeLPWa/516qj1yxO8V+u1UMBgMv0Ab67VusDsYEfSE7v5KZTkwgjUogf4q5XeCIWwe4Ed
LubJStfsqztoYLFM6V0sv5NsalMhV0WVNKMelmuUXuOLYt4kG81FXBy5BHeph6pwXeGVwvmi
ajwiIW6xiZH4rL25nFBtBJ90rrF+OaXzPk2nlFaVyd+ecLTZaO+XzS42FbNsqESuod8eM7ya
9xJ6C4Tefnu/YuCpzQBvrqNw6nA174HdXs3LveDmfgHeXs2D41af2O21vNzBZ3CAt9fy1EAF
McArFF4+N3yxkQhhN9M6mj+ErZdOjG7tdtTyJtnUHvFbvZpVKaheXaPwynlr3iwbV6sialkL
M9houKiW57/ir560t3tsoirHWsW33S3SnuEjwSW1PD3bGr1P0ylSSu/GcWhbwbsTVy2p5Z3n
PU/fHVOuJVMW9TX9pfA2Krzv8vbjiomAA7tZBGjyXTpYyjvAm4VeT2jayYHdXMgr/rVBj4AO
8Pamy4Ym2w7w5lKe4k2NT+xXy7wRBmH3wiDCiqQ2Vt/JMzj+uErmtYumvEk2zsRUpLUqoH1H
XPPVdbxJMpqrVNHKZox2+KYVZuGRqPGrB+3tHpuoyJXm+kTFH7gO9hjuqONN0nGN15o0IylS
QZPURTkd5TSb8WOeDtVWezZpXdDZpb9qTseX+PpldKp1xcHjT3b2Aw/wntDNiz650gAtmwd4
s/Q0fydBcTzAW+9w+N8IwePTT/DW37B0SdbA9XaAt/6FUloCh2Wf0AUflCtPPxsRFXYzoqL6
I2hxukeEZ86uOBG/MvWbYyMp+rfi0NXEuqImLyv6dXPvF9pzik3M8bZSiTplbqgL59fb+tkI
qLjFJmz9imu1Up2U6zXUhHnFVL9v/i4qjJN0lHuJERerrTW4Jvflvn6zdFxFV5PKJcqM+M7g
5eu3SuN9j69fT6gn5YHdXIOiRBks4w3wXrGnxT/TN1z9ArxZ7NXUMjhcO8CbxV6PLAjsLxzg
vWJPJVoVsL9wgFcIvqta48ipsJs5FRI97rWrwulBa44trweAp9hItEA28eVdrXUwEUXWVE77
aeX0Y5JNDPMKmebsMolB66NVE8B8nkxoI6biFptHFFErqqRUawctF1e5+p3SeZ+mo/5/StW1
eFYpYPvCGsGXzc7dXmbpSFeh3oTYyMAPwcvV7we7+qmv7KhQGejtp8pcwOa8Ad6u9jqhw8AH
eK/aK5IaeCT6gG79/TRT6mDU14HdrPNaogo2Nw7wijPlK6OXkQhhN8M6WumlSi/d9/Nb0zqu
XP3m2ISrn0XOsbiwzhUt7K1x9SsX9htTbMKIufrtIe3cBU0oWnMK+7DIv37S3u6xCVe/okVa
tdqrgB8fWhKlcunqN0untIdi1az+rIGxkatc/eSidXCSjnDvLsNdunLsLV6ufrt13je5+tXU
Mxg79YneK/eUUyW0T/8A75V7NfsmFm3SO8B75Z5mf1VBf58B3iz5esTCgTNLB3iv6KsaRTGw
eHSAv/o0d8RC2M3IDg3Dh8qqtYOma4tOcy+Le1Ns5GGjaNZJNFrwdtr7Nboo7k2x4cS1du0u
9V1UwLW9FaqCT32pPx+0t3tkwqgvnIKVS/PbA4ukJfZ+fHpv3qfp+DvjmyWuqqUL2Hi/w95v
ko5/oPxD3zKXzo+0wZe/3ybN9w3+fgVVKAO8V+VlTk1AT5UB3tyv59ISPgo7wHvVfK3+6QRr
OE/s5sKtRf8IesT8BG9+ClsiQy3ED/CSA9yLpXdEQti9uI4og1lR0mJ4LNvXzwRPsgl/P2dC
nbuBnmuLZoL76XzFxzQb5WxMHE5yFQziXTQt8rAovX7S3u6xieleycSVm5FxR1vcvt7fb5KO
35VSH6HCGnpvr7/fL5+1+3fHtMdUkm+QrOJ1ytdQ8AKR923+fgxOOQ3wZh2QE8Fmzgd4s9Zr
vs0B/dsHeK/Wa5Q6+hsO8OamzJ7iSAEeDA7w3r+Qo3KCujkf4CXHuKfRqJWOUIj4H7fUnlor
rvdIW0d9H10iLjnGPT1bm2ZTu2VTiX8yGGfmF60Y226nguJjmo2S3xKrZCaoI9Iqj79TNp9P
2ts9NqHbzHxfwcWKKeyKt+RU+tGefP2o3aZTNGuO8RnfYTSCh2m/2ORvng4Jx7bPWDvh5tQv
tffn1d5uk78cdinY8jrAm4spkjqDRccB3l7SywU1kT3A20t6xOAY8wBvL+pxAQNuB3h/Ua8z
bvQX4CUy77TUUikPKXE3tKNT86XKNIOEvr6mN02mhn0FtUy+e4JdC786s2OajXLjQq4jqrUK
1/TW+Pxd7Cfy0BF3MzvyIyG5FOOS0ZPOr/b5m6ZTpPijpr1zR/t2v97mb/7mmN+Y3EVV2eCU
uddMxgqR910+f75NQQ2dn+DNKuBRA0Ptfp/gzVqvp1pBT/oB3lzSizlFtEBwgDe3YlJqoPvH
gd1c0CuporveAf7a49tKPOTE3dCO0lrXUnIBe+V31PMmydQwcy7USxNwp7CsnHfaoDdNRjO5
/hZWqbXAVjhfHNkx2LzdYxOFuTj/0eJKQgnUravKeadeOO/TdJwHd80Pb8naUfeYry/nzdIh
pVKpaqmFQJfMv6rVH3+F1R86xLd7ogAs+Cx4bBeo4u+xH/TlO4OVsQHeq0aoJjgB44ndrIgt
dfDE48BuvcNCLnENtOIc4K2/YDGO9hrMkOaJ3fr3iVrMGoG/4AFeUfk8VV2uU2SorjvRBpwo
jrWkFG0uvMAtSFoS2HIxpzzJRhK7IFbKVrT3jrGRJQ4uufWLetTkvRHruWYNryA4UGfyzPEP
UxEXpU8ZmutmiIb41059v8KWUbOg2UnYf/WjkYsq+yQdjWgT146ZuCm4eferlrQzngbQfMzf
HfPtSs9s4XYJDsW/ap8/3oCwJd/LY5+WAd5+2K0dnW04wHvlnpYYmgHLiwd4r+DjqAuj9nkH
eOtvqETJ1zlsTRjgvZKv1SRgNsiBXSL4LgpTZYiKOykHnLI/g90Xr5xzQXs004oGkivH6Uk2
4TjN3C3nTnF+jwq+JaZw5wkU0/emSDaRwlRKZ6wqxUuOU7PZRUdjGZLiZtqJVqMuwUkNXGT8
qhUGhNTOpnrfp+loUeHamboyuPfzi1b4Z9NVtX2STXHdatXCuN/3+Kj/4F+zAvpv4T8oYR8N
TtkO9PZ+st7AJvsB3iz1FJfLA7xZ6lkqBp4FDvBeqef6sjVwfGWAN0u95t968Cd8YldIvdNT
Ll+AdciJewEW2V/hLDEkwehEwSKpV0/Ndd4n2fgHiZxP5HOVjnrSy5JqmEu9i9re5L0pImRU
qkhFW83WSD3/cv7ySXu7xyYaFIvfnFZza4za6yxqa5R6psPfp+mU3vy98YdYqWiDZ3tXOIFT
uTjtnr07pcfEdSuRfoDX9qak60vr/T4ehC1RAQvtn+jtjWVFOjop+gRv7hjIvulBk0cP8F7J
pzV1MM/pwO4VfKX6pwQ8vhrgvYLPehIGNx4DvKK9kS8W4jpkxc0Ii0yNXCNxVJFgm7sVnn2X
km+KjSTxdYtzJJYxgSN5MhmK9a/HuXI2LPExfW9KxMs2i1iOgo7vfbWx8eeT9naPzcPYmFvO
lLWogpXxVce5pxNg79N0/KNTKZS+qv9POF5kyfbCTi0I5+9OrUVIOimbKCzIpx62l+T7ZgtC
M1BCDfBeCWWWDHVxfmI39+txqq3h08oB3ivlu6XOqD3bAd4r5CPMhNFj+gO8eauRw1AN3Wo8
wSvqelfVljaExL1sEREqj4b8ntGlKi9ZeWPW83zlnWTjepW1KftPJWC2iF+0QrLaVR/VJBvX
QtRj8rrZY0gGm2JZcUqY22mG3GDzdo9NVI60uZDg8NlRMKl0tnL0h3HliyPcSTqliGk041bc
YWeFAeH1DMssmbCHjAFs8+0ReKDysqT54QaEBRx8GOC9ayzVyOXGRzMCvFnrtaghwv6DZYUG
uBMoQjmZoL3eB3jvPVZKVsDQrCd2s86zVCqYETjAS4p5F640fWiJe3EiUk1NYsMmAiae5sk9
/B9saS4W30k2jTiGTShrY9D5JC5awKbbmTL6mGajWmOgoRXzpxy1UlwS9XJeLvp80t7usXmU
i8R3KhRpzhkcDZstF/3BfPBiNmOSTlEXqzn6BWIwHlZ6KzoPS74oHM/SyZWrS/FIDUc/BH7V
1MLwUnrfbD4IN5cO8GaJF7bRBC6vB3h7OU/IwBPbA7y3nGcPGxKwIPrAbi/m1Qaetw3w9mIe
GViyHeAVIu+018iXXhtC4l5mhfguzar2ltXQfPDJrKg7xbxJNi0zR/6duW4FaxKLinmXIm+S
jT6S73LjboT2gCxq+T9tA/t80t7usYliXq05al8xlwE67Cwr5v3yUbtNp5Tc/dNYxDcUHa5N
LirnXQxkzNIh6t3vTOm5KW6Y/SrnLRB532U+6JsTVOs9wZu1niX/7oFHZgd4s9brqcPRcQ/s
5nJeS5nAucQB3lzOK4kNdAke4L1/oXAEaqJG2E/wCq1Xzici80isyPcSK8SymNQW/11Bh6BJ
j4UbWm+WTaNerDTzJ6KAPf+LtF4r50WWWTbqC3bJVRuhCbRr6nlMdF45ziOu4haZqMzJI6qC
I48a3AsvqudRPq/nzdIpvj0SJdIuxODOeVk97zy4ZpqO7+pzrdylaQG/vX/Vep58hfsg+Iis
qKv8XJ8/TZyxWvKB3bvs55aqotLpAG8Wn5bivAQ2+gvwXvnZW2IG/c0HeOtv6JvdyHPG/sIB
3voXit+4hjqwD/CKvkE7LzXmEaWR70VpWI7TV63+X3DW7wq1f+n8MkdG/IMUHXb+rzDyhq3+
VrDp/byZa47NY9NSjZmqKwJwmIuXVIHjZ/zVg/Z2j03YWEv3dyEqp1lB091F5tdSLzY6k3SU
K/vGoFTfWXZ0GnhJBA3l8w7V6ZvT/ZXxDWFRKoLfnKk99e+uPv+tnP4aYZ/JA7u5yiPJSNHs
4id4r9yL/JemYLHxAO+Ve9ZTzeAZ4gBvlnstFbRgO8B75Z62ZB31SjzACzQF97MPva/CI1Aj
3wvUMMmdS5wpmaI2AH7RivbBeqH3pthIys7BrJXWWUEPi7hoRbWRz+cz59i4dMtqIr2E8R76
1Usrto9MV3XtEadxi03MAkeoNBN3c6kPh52smQU+71SdpaPi26+Wi98dbuBI0irBd7pT+pi/
O0bUG6k0CSOol7XzZsG33eqvJKugp9QnevuZnqH2FE/sZq2nYVcPrpkHeOtdjlwOzeCqPsBb
f0PNsWCBRm0DvFfrVcIHvwd4hda7GAnOIyoi37Hvd9mmYo0pd20Z7CmJi1ZovYsYjzk2kcjR
uXehRs3AcTJZ4ibnWu/c1XmOTTzY2VlkkUYVdnVeovX4IjAmj6CIW2wocXMRXnORztLBJmG/
asECw/m08Po+Tae4uifLMUab0XxpWuTKcxqy8jFNR4SLiOs864paWs0q8ZfW+32s/noiOLl+
oPdKvtKTb93RoYIneK/oq9m35aCHyQDvFX1Z/cuDCpYDvFn0+Y1j0Dx5gPeKvhZztWB974ld
Ifn0QvKNsIh8x8E/1JtWqhGwIIr2Eq6YdLqu7k2RidNc1VyotswChk8uOs1tV0dsU2xipIyp
5NabUQVfBl7jhswXnpJ5REXcYhPazUxbyVT836B5Ai1J1XNp9stH7Tad0mqr0lrWzg0sk4Ql
9IJnzeyib3WSTli8s+8tuhY28NWhydaBl+L7Zqe/BoZaHtjNHXs5RBvYsPfAbu7X49QyGtR2
gPfq+C5JGbWnOcCbC7eWVNCuzAO8+Sn0zQ2jiQoHeEW/XjtPTM0jIyLf8e3PvvCqxfDpMzgV
lHhL0mxLv2jin2RTW5dSVePEHLUDTUtGeSxfNOxNslF2EZGlFW6lomyWHBHyRShgHgkRt9hE
AaiUrP6QKYnCVbAlB7jEF/XjSTrFd22+k8hMtTfY/XhFqwnn0yC9j/m7E1aSNffipCrszvMa
DV4h8b7L6U8JrEQN8N5VlnvqHdUBB3iz2mu+o0ZPwQ/wXrVnjxBx1Bj7Cd5cs61xPoLWbJ/g
zc+hpGgJA5/DJ3iBojhPIPA1eMRD5DuW/SHcRF1RSO6kslfttYsqyySbGHZSo+b/QPso/Jol
J7gXHVSTZDR361oLce3oJyWtGKW6NHXOIxviFpuHqXPpvqMo6mICfHdW+cCcJum9T9MppRpp
rpVaNXDYLUaKl9TzLjYWs3RIG1GzLNkYN/t7BfP+ebG32+yPUgP7QQ7s5koKp44GoQ7w9ooe
M7q8HODNFb2SKmi1dWC31/MKOjHyxG5+BlvqYMvUA7qikicXoxgjFSLfS4Vg667rrGbxZRc2
+VvR0HZZyZtkU7uU5u9TxJmhvi9LCnmtXHTnTZJxzV26cOXojocDO5YU8n79oL3dYxMlOY2q
MWu4OXc492tF5Yv0bE/0Pk2n+IOmvjH377YSPKu6JCb54ZB4/azdvzv+9pu13Gpx5Q1L1Vch
b4G2+55CniQz0LtsgDcLAE3EYE15gDeLvJ4amhfwxG4u40lqcHzcAd7eepkJLZId4M1lPE0G
9w4c4CVlvItZyBEMkW+GdhBb05KJKOOhHUuk3lUZb5JNrT0cH5v2jAvXr6/jTbLRbMUfnVKM
DbTYXVPHy2YXh7YjFuIWm1BtzoVErRXOsNT78jLeJJtSWleq5NsvyWB/wJoyHhNfDGLM0qFm
pFz81nTK6NDtX7OM9yUef2hMTV6hV36yy18p4BDmAG9e+in56gKeMR7gzQLUfEcJh8Y9wVvv
MveSlMBh4AHe+huWLqkraEQ7wFv/QikxFAXa+wzwkr7BC2EwYivyvdgK1za9tVy7aC5oSctW
SNBLo78pNpJYmj2KWmIClqr9ohX35mH2dqYLptg8pty7SamP0z10MmRN2+DFXmdkVtwiE459
vlMkf1Wr61tBZ4GX+PzxVbVxkk48Zb416M1aE9CFcYfR3+zdceHpi6X/X1cR8BzvZfT3443+
egxsYd/JAd5cjqJEApejnuC9ii9yLlATuAHeq/iijsjgwPcAb1Z85hIJjDIc4L2Kz2+cvwCg
ojjAX6z4eIRX8L3wCld8rdQwYaMCH2IuUXxXw8BzbCTlakquXo1dLKGKLy8pOl4sw3NsYq7X
5XjPZNIr+D4sGgam05iUzyft7R6bEG/WtfmrUCopWLGnNW42wuetDLN0VFi5qDV/cSq4u1gl
+ei8mWH67vhCZBaNqkRV4Tmel9XfIsm33eovgjkaeC4z0NsPmP3NBZXKAd6u9jrs9ffAbtZ6
Lo4U9HIa4K2/oOZIKcNu8YHdrPRaMgOnlQZ4gZq4MnXmERTBNzM8JNeuoqq5g52Rq0ydL4z+
5tiEZ5+/7aU0NgZl6yqfv3Lu6TxHJjydWWpuLTL+0PTsRcUwOZ8S4RETcYtN+PyptnAurDGM
8LvY/M2yiXFgKS71Wo2JpJ02fyWfny7P0hG2MBcyDd8k0BrgZfP3823+mt95tA1noPfKPWVf
bcCs9AHeK/dq9m8b+H0e4K33WagnXxRRb+cneLPg6/4xAa2Inti9gq/W1CqYqzDAK0p7dqYq
fB0eSRF8M8UjZykUXQ/WGjoWbCsGYS5Le1NswufPufTetImggm/F3Ftup05yH5Nk2L8MhbOo
UHO9h7UTxkVLBN8vH7S3e2xCu0npRiIaVjBbjZ2vbP5m6YTNX46QM+21GtyAt4IO0cXmYpKO
vy6SKXMzqw1s9XnZ/P1Im784C0Nt/h7YvQovcwoHTXgsOMCbG/Y41Y4aOR/gvUq+c1J4cPkA
by7bWtIMTi4N8Obn0Lc3DTweHOAFQuKxuTlbekdCBN9L7/CvelbJPdeKFifykpX3cjx4lk1t
XXtX6024olMWS+aD++nR+sc0G2UpYhQpEQZPOy/xfjnPh/h80t7usXnmQygV33lntr1JbVdG
f7N0ilR/xJhd43GHo82WGP1dzQdP3x1z4U0kmbOBwfKv8eCf7PNHyTrYcz7Am2VAToTOPgzw
ZrHnKzs8nPHAbpZ6PVUBS1EDvLkfs/l6BcrlAd77F3JodLAfc4C/WuqNaAi+l9rBndjFXith
bIH6Bn+91JtkUztRJu2txwDAViuYi/HgWTaas0TyXPY7A+4e/ZoFZM5zIT4ftLd7ZKL0w1Kp
CLdO1uDU1yXS6GI8eJZOzGxHlnXxxxgtj2xw+ZumQyVXV8RauBLYmfKSej/S5S+nXEFbygHe
XEgRF5YFDe54grcX9BhtMBvgzSpPUkV79AZ4e0FPDJ0RPsDbC3qPRiawnscrWqcunZx5ZEPw
zdwOy7lpI6vFwFaIDbkds2xqFxIViTNysMSyIbdjlo1yi3Y5FxIuJtDj9C/P7eCRDHGLTRTm
xL/IEZPcGtPX9oHdsPubpVPE/02Ww3GogHvmDXZ/03fHShaK1kNuGQ7Oe01jrBB532f3h50R
HNjNGqDFK4ZW857gzUqvp4qmGA7wXqVnvrgxeDA6wJvref6zlBtJywHeXM8rydcsND3mCf5q
rTeiIfhmakfvtfvS3n07D1pGbEjtmGVTG2fy/Z2zkY4GXXy53d8sG805FxPqHR2RW1LOuwzt
4BELcYvLI7Sj+7euRc+h4lYrX+32N0unlN5zc21EXRnMz9tRzpulQ1ofUs9lZIbz8/6abn/8
493+bk0TgHMECx7cBbr4uzwIwaamJ3SvFqGauqK+DAd4sya21Cr4yR/gvZqYRFJFAws/0Vt/
RaUwMwb3Zk/s1r/P5VYSX0GwmYgDvEQTn+ku1yojUoPvxBzUZORroLqILN1XRYhRXeRGc5rC
/D7JRh42y+FIE3MR4MyTLBFeucuFJp5iw0mNLf5Tiu9XwB2YX7Si/kkX9c8RqHGLTU6+3Ctp
YerSGa3m5iX1wnY22/8+yYaS+paOwz9eFQ5Z96vWWGBfmNFM0iksEXtUOEyF4YGiubPF310U
/3v5DzawxjjA28+7wyoNPu8O8F7Fp+WG4jvAmxVfuB6CU3UDvFfv5eafEnDMe4C3/oVFOBFa
mRrgBariYRt5tg6PYA2+k3bgm6LM/qFv1qwIuJeqa9L6LhXfFJtQfC6uNVJcioAeO7Kkcy63
elY5/Jhkw6lZNnaZn3tDh4viohWKT85ExeeT9naPjYs331Zws27aBA3WTHmFRJLTE+L3STau
3WokKWarTIXg0JMVDeIXLjsf03RKCzHeqXQRBUfzZl12XorvN7AfdOlR0LPQgd7eVGboUdYA
bxZ7mqSiowAHePN9NvWdNtrJNtB75V7xW0fgfR7g7XKvE1aAPLBLyntnX3lfgkeEBd/JFWjJ
P++mvmB1jr4ziJBftIKNnub/vk+ykaQc6RW9d3/xwerrkn7Af9Z6/w8AAP//7F3LjiQ5jvyi
EUiRFMUfKGAzP2N2D3vYmcPu/2PJCFceuuFedLVSWVkdwADTB/PutPCHTBRp9scFeIqMy7Yu
HRszt0qSdaRZovUQLs68R4DFLTZYwD8lLforTDk5weIXLTnB7xe7iik2rtpAEKoxmgnltd4S
OnY2ev0+TYdcg1u0bXSyfDLza4BlldT7IgfCXjCbdXuAt7eWSc2aJR/gzR0DWJJ9YoHce38x
CmGSHX4c6L1KT3tRSv6JA7xX6XWN3Nxs2N0T/MlHuTTCK+hOoEArUTsCM1B0sZf7zf2iFYm5
V1pvjo3rtrC4c2UUq3CyTBkXrRB7dn6UO8sG0BpajwM2TJbC/KIlzjR0niVHI7riFhvXbbX5
Y9ZdwRKlPZBgxVHuVa7IHJtICEHXRdC5trg7WbG3JkrufJJllk5MXQtZjII1TpbEZ9s1X2rv
S90HY8GEbB3lCd6rn8yKZe1KBnhzw14tWfPhA7v1HpNKyX5iD+xeDR82PdlsqQHevMvQUi0Z
FzXASxTeeQsVjdQKupda4XjmaGdikmROfVy0gM2jN/Bs3Z1ig/45InNJbWYI6SA8XcGmn4a9
vE+zEaMwCxIW6HnvwSXlvItRKRqhFbfYQGmdEVTbI8sZsyJixYFRxVODnbdpOn5TtFeuYcxc
kzWRNSMsFeQ8UmSaji9FKOgCrzqxNJ3fcoTl72E+iP4w5t7CA7t3jYXmW+9sjtIB3qzztIgk
rX0GeK/S6+GFk41QPcB777Jo6ZrcbwzwZjUaHeNJk84BXqAnfOtyvgKPwAq6F1ghBqy9dezp
9tI1zf/YTpv/3ybZuGyLMK8qnf1CzZoP6pIR0tOK0fs0G78hFbgZdEm31CzR4b7qX9SNR1zF
LTau2lzhCTSUsA2qOekaVy05u70o503S4RaPmj9mj+POrJPLkvi4c9vs93k6FHPkZNCEHpMf
n2ib/dJ6X+w+WJmTh2UHeLPMwwKSbdA7wNvLeZR1oxrgrXfZF44CSXvEA7v3HjctkHaYPsCb
RV4rHZINU0/sAhlRT+c7feEdcRV0J0KgFhOsiM1693/Irbtx0YoD29Nu/7dJNlhiZKFSDBBJ
ukW2rPg+uMQ7z/CaZaMUU6rhCdkwOYq+pjhZ4SIvjkZYxS02UFwRgRqZb8hUk82GcdWSE9vz
KJFZOtyZY9Pl+wloPa2JluTFXZ3YztJhVTRlBNC0Xn2d1y4QeF/lPCiclAADvFnn2Q2X6QO8
Wef1YpZ04BjgvTpPrTRMHjsO8NbfkIBKS5pMH9i9T2FvvpdP+o0N8Aqlx+fd8TTSKuhOhEDE
4hpE7zUjZc1l/aIVbNppr//bJJtagDSa/V1RiHB2SnWJA04/7fV/n2SDxcLxV3oV60k3OFzS
NelC72JLMbIqbpGB0ltjQuVWWwzdJsVEX1L8unBZmaUj3KWKtsiseczC73NZwX6xqZilgyrQ
EYx7s3Slde4g6leXevQZ1oPJ3KkliVPLxkN2W/xx6cmy+IHdu+yjllaTiYoDvFl8WnhZpz3+
HLv1DiP4rxLpS8nRnwO99Tf0HbwrgqT10ADvlccSrYDZ8/gDvEJ+Xli+0AjSoDvhBq2oKUPV
3mvDZIUh6qYrCo18bnw9x8Z1MRGLS1B10Z8s9cdFSwqN585rc2xqoe7qBnxX0BGzRyuTuRN/
VDh00Tc4YjRuscGC/vxinPSjtXRkC66Ym60XGSdzbEJ5GTSLsWauvWdz+dZMhpy+OO/TdMhA
iLorUAZKO1+/Mk6WCb2vMvnL1sgP7F69R1SMs11lB3iv3hMu2VPvA7tZ79VW0LK5CQO9V+9Z
Leif0pzeO8B79Z7WojWpSAd4hd479XvwVXiEadCdiINWGvWq3GIIUDlr6rxkU8ync81vk2yo
hLeyAIloHPsl9d4K43fXe2ea4n2STS2M4a5l7KR68hCoTrbu/1EhXZg60wjTuMUmpJsCuebr
ZKZpvbeielrh3PZljk0oN4lz/xigZ03mJ0aRcsWjdpF0MkuHQfThMASdsoX615jIN7b4kwLp
QLaB3iz2asl9JR7IzTJPCmnWMOcAb77D2gpnz0E+0Ft/xbBnphtWzrR5ECiGpCPKPT1RHeAF
3/dLw5eRD0E3szuqdoCKqlaTq5VftKIQxnrR1DXFhgpV39kpAzHU5EA5LYnHRcOLtv0pNqHY
oqezSmOtyVOpOpmncMPdj0Y8xC02UMwqRKOvSqvpkYoVxx4u8y42FJNsWJtviyqL7ywkmWK+
qH3wPG7wfZpOxA36+w8Y8YnJQfrZuMGXzPuV7P0Akp+WD/RetReeM8ld4YHdq/ga+qqTrewd
4P2avkvyzO4DvVfxVRcVmuzFHOC9ms+iKJtM0Brgzz7KHQkRdC+9Qyn8/VocFtb0Ue4S05RL
zTfFhkqNdjWt1JUeARS5o9wVGcadLzTfFBuXb74QM0Y6RMN0XtsSk5FLzTcCIm6xCfnWIc5x
hRny/jywoGvgemZkkg53JmZjcR2rlO29WzMzAhd2Q5N0qPm7o1Gw9M0fpM9ypz5rL9H3pS5/
VqKlIuny9wRv7tgLq4Zkp9QAb+7Yq6VhVisf4K13mZQKWLLrcYA3i/mwVkh2+z+xm59CKx2S
J8wDvKKwdzUuMqIh6F40hD9+0MC6xEqVFRJLhl9Yz46h3ibZYGm9xZRm86eCk084LrEXQaWL
Q7VJNsIuv1nIADAZmIxLjggrynk+DI1kiFtsoDQ1QiMnpB2TU9uLfP7OzVLepun4ZiJKYWIt
4i7Slb01B7gXDXuzdFx4V0bl6A9N7rBfwR3f2+evZhNaBnjvKlt7ManZzI4neLPWe+TDpo3+
HLtZ6fWSbYQ7sJt1nv8mPVu0fWA3P4GtWFYpD/CC7zue+rj+R+ORCsF3rPpricQsaOSrFrWk
yYhftKL8xRfGa3NsXLJpV4PH0Zqm60UrpMSlzptl4wpPXYeTAEv2c7JI57WzctHHk/bjHptQ
bDFwClRBKiTNkxZ5/J07prxN02H/6jx0Hiha0oFxlZ/zhZ/kNB10jaemguivUFrnvRr1/rrO
2+/xB5Scyx/gzWWUGkeIySrKA7u9lOcfseSB6AHeK/A6x2FDcpDgAG+WeFJqS0aEDfBmkcfF
F96syHuCVxTzTj0sfOkdwRB8L7RDgbSCuYpI90L4NQvIiJ53yM+RwRh6URIRI7BkLERctOLA
1s4P0WbZiCvWqsy+RZCktS4uyZircJH1zCMV4habUGuqUqtYa0TJHRwsedRCVf7sUbtNh1kQ
mLEJdciyWSTxzl2GptmAcqVHonCzZHvrS+J9Z5c/jtbxbCnvCd67xpIUaNk+lQO8Wet1XzuS
wwQDvPUuM3B8p3J/4QDvvcsNCnAywnyANz+HVsKwLPkcPsErCnp8Pg7JIxiC74V2KMZgpzCT
WfY3XyOPrkI75thEaEcYUxMagGaHjtaEdvRT6fo+zabFVKchNOmctECOixboiXphtMIjFuIW
G5dt1dQleEcEheQyA2sMqqld7Csm6XAc2KL1uEGW7ARdFdpxGm34Pk+HfDkXAu7Qe/K0LK76
HdXepxj9YfJHxRWnj9/a6o+SX+4B3lznwYJZk7UB3qxBzXdh2RmRA7z1LiPEnesta/9yoLf+
ii4kCiZXqQO79e8jqQUgqdgGeMGH5WpChEdyBd9JEwizP/+3+qKjFYhzdZO4aEXB8cLsb44N
lerKQNhfeyGWHBu/aIkG7edJD3NsaiGRDrU9alrJQ+U62bR/w+yPR27FLTb+MXap5rqtOiVM
ppMuMvujdlFvnGIT5i/gyx8ZUiOknWZ/URP82aN2mw71SBWhhw9UtlE1rvodJejfyOxPSwfI
LbQDvPnsEQpkNekA71V8wsW3b3m/vwBvVnyuhMmS4SIf6L2Kz7C0ms0/OcB7NV+rRbLV5QFe
ofkuDP94ZFjwnWCBVhp2Rm3id5k0txK3RQMjF4Z/c2zCu0+aCwpQ1XQfhe8MVzQSXhj+zbGJ
iMnIbvVtYaS4pg2el0wFX2m+EWFxi83D4Lk36/7NQ0ieHa0yeL4w/Jtj8zD8a+IvJKI1SR+Z
L+nyhNPjh/dpOmRs3WqP7VJLKvKXwfO3Nvzz1T1rB3egtx8yJztrntDtUk8t+wMe4M33WH1p
o6Si/0Bv/RUFuaAkhwcHeLPUC7fGpMf4AK9oJ7ww/eORF8H3sjzMt/SowgCEybaoDaZ/c2zC
9A9F4tNkkHWqjotW1FxOx0/fJ9lEpQ7IhGu0rWUd7ReV9y4MYHjERdxiA8V6t6b+NWH///QR
8xLXP+zn+dSzdFipV1d70Fzl513/lhwxw3mW3Cwd8o+LvzvNN2D+DqVd/6ak60vr/Uquf5Y1
/vpA75V8Uot/B5OfvwO8V/a1mJzOWlEc4N33Odqv0rLvQO+VfTXCq5K/4gDvlX3qjz9jNtLj
CV4h+05NXn0xHrERfC/SQ6H5hx4ebV/JDYtftKDucn2qO8Um0ti6YofIvM7GRsRR8GdX+KbY
PCp8ZP4vDj+2dNfnmgrflewbqRG32ISAowjz4AatYtoob5HsO7s5b9N0Yq62ViHfGoer0lbf
P74YS5+kQ87HhHz7B+lDqpfZ87f0/etFskEKT+xemYe1xI4qPSkc4M2te64tKSmhntitdzhC
xHw/mvX8e4I3V28tqgDpyQxb0fp46xnshbOtwAO8ROBdtO2NwAi+FxgRWgjs0QPfsu42S8YT
rr1gptiErYvv7EAY1ZK5qausYPiim3+STKg6MTNgfwOT02hrUmCvLP94xEXcYvO0/Ovhgky+
k0iOXW2w/Julw6Ti357oeG01WUJeY/lX8bST432aDlmPeSvsfouyJYqX5d83t/yDpIXRAG8W
AVgAk304A7xZ6GlEc2TnhJ/gzVJPi9XkXR7gzX2ZERORnQY/wHv/wsr+dUz2EjyxS6TemZ7w
FXjkRPC9nIjozbGI1NKKyVnHZbZ/FwvwFJuw/WN91FeEOW2i0pZkeOhFC9UkG9cS0CGOb13k
ZwNtZUlu25XB5EiJuMUmVJs08l1jB6ycjgb7fNu/STrM2mpzfUS9QzKpc4cnzCwdULAIPHTR
p5COJHl5wvx1rbff9o8paRMywJsrKVQMk+XGAd5ezUue2AZys7yL0lJyLz3Am+VdLdkuwgO7
Wdz5spNsyjmwS8TdRYP8yIfgm9kdDePIFLFpcogwrllxTgsX2m6KDIZ3oXUgX6UqJY8CcY15
oavj8/V2ko1/WUUY2aBL8tQ5LvpsbTfCIW6xeVg6V+psrftOJ+sZvEbaXZXxJtm4BmKwsOZB
10NpLfTZyR3TdADQ3xttzKR5g+pXGW+BtPsquz+pkmyGOsCby3iRdZF8FAd4s8LrpUnyLxzg
vTrPsFjW1HGANzdfkn9Fki1vA7y9nKyc7FwZ4CVa73zsVkZGhNzL72jUGmujyGfKNryWFcmC
l2Jvjk3oNm6+BPvqa5SMiFgk9pTPm/Jm2Yh0I1SkLpT1Rior3tZa6adP2o97bMKl2WUeWERn
A6UnO1f0f1bA8/aAWToszamoxIktJW19wiRwAR3Gc7U3TQfVUKX6goRZJ1O/akoAfLXa26fl
/uff//r3//37X//9z38gwD/+87/+959bF6rc93z35EJyZmHBR3mBFv8S08OqBbN2tQO8VwGB
/0cleSsHeLMSN5cpyXrPE7v1HkevISeLaw/o1l+PuxXMWn0M8Na/kHwDaj3bjnCAF3xSEM/j
VWRkeMi9DI8G4PsYIyZMzl7ENSvO0i/GoefIUPEtd2vaWaOyl9xmlrrkLJ3OR1Tn2NRCWtFq
lxalhPQ49IqB23oa0vbxoP24xwZKlV7VrEVIkCZPyvyqJTsKOZ+LmaUj1eU39IgjAU4OlK6x
O/QdxXltf5YOheOpb478/qgkl66X3eF3tzuskY+btTs8wNvP1ZPn/k/oXp3nS3vLhoMM8F6l
x1os3Xx6gLf+hgKPobxkA+8B3qv2Wi+abCU/sJ+t9UaEh9yM8ABCX397bZCN0F4k9q6GoOfY
xBC0hI2Pipkke/MWDUHbRTPbHJuY7mcmUSSsqNmm1hXGD7XS+eG6jACPW2xCtjUTMDB/3rRn
660rlHgluqi3TtIR6uqMWLU3TsYtLPM5PM9LnqVDUQcX4Gh/yMZQvk7Xv63PIQKG3VHyYHig
N+s8lx6ctbU+wJu1nvgWNq31nuC9Wk8imSQ5YDnAe7VeFf+KJNt4n9i9Sk+x9JqsLA/wkrP1
ixV4RGXIvXAJ32ooY3dtpJbsq8E1Z+uNzoZu3ybZUKijir1Br/Y4gMz5HC4ZiL6IMZljUx8+
w01beB1i8vS2TtoM/6mwdz6OJSMp4xYbV22ETAA1hrEwaWMKS6xqa4WLbcUkHRd50KAyNuuP
1saNhjcXPoezdMg/LmDE3eLVedkc7pZ6X2JziEAlm5I9wHv1XuUbziMHeHOrQHhQZGMSD/Be
vdd6sWQZ58DuVXsMxTRb2TvAe/VeN79tSdvkJ3aBoqh8ofZGSIbci5VoTar6iqXISNnRjCVD
xHyqXd8m2dAj8iOO18Sw546iaIkfINqFu+EcmepfLv+NwkVWELNJnZNDqn8q7J3bp8uIyLjF
xmUbk98WdW2EAslDaVhSda2PfMnrJ+02HX/QQuqhvzxoPe1+s0KKP4xVr5+123RIavcbhFIh
HEJf7obb1N5ud0PppYtl52We4L36yax00+Qp0wHe3KVXi68wWdubJ3ivjm8WAyZJCfrA7lXx
HEfu2YrjAd68z4i29+T8wgAvOb29qLOMdAy5k1iABXsHv8scibGaNQVcEuvWrqZlJtkoqCn5
/7Bz8juGawy59bQ++T7NRrhhzHiTNWvZQe8lo9H1VLJ+PGk/7rFxQQCE0XlYfcsoyXp9XLXi
9PYiD3GWTpyrd+7WTbAmn7VFFodXKXXTd8c4DNN9t6y1pW1vXil1K0Tel8xGN/D9PSePzQ7w
3lUWWpTNkzrgAG/WelqSdiJP6F6dp600aEkleoD33mGB0iE5mjfAm5WeFm3Jw7QndsXJbbto
lB9xGHInoiAkW/fNuwsjaZA8Tgtb0xW1vH5RYZlko+HFC6bhy519whdNRV/pvEk2wuK7aVeu
0rMZaKsscE7NGj+etB/32LgmQDbjLjVyfNMRaGuGos/dDWfZMCuRcnfxqk5rp7shn2733ufp
+BeUw0UztqTJHezL3fA7uhu6ZEvPOw7wZn2HBSSbqnCAt9fy0oe1T+z2Sh7VfCXPsZsreTVO
N5N3+ABvr+RVyo5BHuAllbyL+soIxJB7gRgYgbDEGuY36XiPJZW8S9+bSTYxNshh4dFunD1/
vsKbZCOs7AqiI7kK31zJu5j4GXEYt9hETa7WTuzao1HW/H1RJQ+uhm4n6TBV681ADbGmC5O8
otWQTjsn3+fvjvmDFj2gbD0drfcq5K1QeF9TyKMCWRfrJ3azzLPSk4FvB3azyOslvB3SBocB
3lzIs2LJadsDu7mMF2ewyVLyAO/9Cym+cMlP+wCvKOTpRa/UyMKQe1kYFbr57xdRsDXbZlBW
CP/rQt4kGwWirmCuWhGyovXzZd4kG5d5PQJtsQMlx22XFfIu2j9HEsYtNlGTM7GqVrGJpNvY
VuzgKtqFzJukwwIuXBEqt9rSQwufnlMyTQcsKpLkKhxq3q3xt6zkUVrn3Vg0kucKS6bblk2G
7Lb1a8WoZq1enuC9Kz9qyQ7DPaCbtaeVljbNOMBb73AlLijJUc8B3vobcvc9jSY3GAO89S8k
3zRAyy04B3aF9jzVN64IRlaH3MzqaMw9XF6QW7IRfI1987XVyxQbKrWGy4svodIlWTClJROm
2PuF3fEUmzh88DfPwEUbJ/s4/Zol47JXteyR1HGLTNj61YY1+jiFW3LkMK5a0it4MWg+SUcq
otTew6mrJdtJYE2AIcDF8NEkHVJh37GRWGuYXL1etn7f3tbPirWkEhjgzVUeKlY5q1We4L16
LzJmNHkoP8Cb9Z6WcKVK/oZP8Ga95z9Ltrl/gPfqPZGSTcs6sEtqjed6r424jnYzroN6FxMG
iWJDVu+t2BDzRcf+HBsqSNx8k1dd8CUfn7hmRanxwlp3jkwtNUo/LpPMJV9yNqSuOYKteJ6k
0kZWxy02odz8Swe9YRfMTx8ssXG+0nuzdFzvAQOyS2N1alv13s+ftdt0qNcKlZW6a3LLyteX
3lul9zY7+4FZ4XRVaqA3S71aLHvqPcCbpZ745zY5vTLAe6UeSwm7hWR33hO89TcU9AXYJVyu
t+EAb5Z6VjDrODTAS8Teed9+G8EQ7V5mx2OcUaWpy/rkTI5ftILNVWjHHBvy14mhVzDttbWk
Gc8SfYTK535rc2xcuGGtriKxN5f56dCOJXYv9YzNx5P24x4b1221mmLsHCvWZOU+rlpxsNzP
fZxn6XCLd0YMoXPN272ssKXG06z092k65C9MTEzTw4wnfew/tVF6qb1fx9zP95Q9aSX1gd4r
+riX2CUmBcsTvFf0NYwkieTieYD3ij4JI7RkEsATu1nyWbGelM0DvFfyNSuPQcOMonhiVwi+
ft7G30Y4RLsX3CEKqLUbV4Jk9HNc9MmnuXNs4jQ33PDCKkWy8pWWaApUOLfjmGMTH1fFMJAj
6JCtxpf62WbObURD3GIT0s06UaMerjyQLSAtMXPGflHem6TDiuofRiH2e5/cXCwSfP5L/uxZ
u02HfBVSIajGzdKhcy/Bt2BiZL+/n7/eeX+/AG9u18MSTunJhr0neHPLXi0Nsy7YB3ivlG+t
qCRTTwZ4c/XWSk+q5AO7+SnsBSg7s3SAFwgJbOedVG2kQrR7iR3YrFYEMt+zpX1fcImH81Wp
ZZJN62joq2+4VyRP2OOiBWzswlh3lo24yvO7I2qUdUHCNWGv9aI5tI1MiFtsXK75VgxNOtTW
q6Rtgpf4+53aFb5N0+Fqvrb4HriZ1aTL16KpYDjdHr1P0yHzPR6HXxIzJl+d11jwd/b3c3GU
HBo9sHvX2NpLVMyTzhtP8Galp/51Sjs5P8F7lZ7GcpCcC16zctwq1zbfQGTd/Q7w5meQCkNW
5x3gFcW8Cx/nNgIh2r2sDozRjAjiVZJkA1VctOT09qKYN8mmKbqQiHIem25NHtF6sfZOshHf
ZXFVVpb0vmxNNxheNYWOOIhbbEKxiT9iriI6hfPxVoO/etEoMEmHqVNFFvL7Y0kTg0U+zq6W
f/as3b87EaNCrarTackZ9FcK73c0+BMr/m1MnpQd4M1llFp6T4bbDvD2Yh72bFnkAG8v5rWs
x/QTu72Up8nT0AO7+RnU0jnbMnWAV5TyTmOlfOEdcRDtZlSHRlpVMyN9qJSNpbxTGfE2zab1
BlGHkubrVJbNEntt5XPTtVk2QtEiD1Y7aTbOe0Mpb4RB3GITpTwVDY9twDjp3Grwhxe7iUk6
XJ97CajJXuJldbxz25dZLtQNIhdZgChr7v+q431vez+CbN7pAd4sAaRAfuz2Cd4s87oLj+S7
P8CbK3lckolnT+j2xkuU5DM4wJsreVJaujP+AH+2zBtpEO1mUodiQ6ikXR9r+06Zd7H2TrJp
rvO4Rp+/ZQc7d1TyJtmIv30GqiwImvZxXuPjcTF1O8IgbrEJwWbkr6qJP20t3Za3ppInF5W8
STrMIOR7CX+/e3b+fk0lD81++qzdpwPQKJK3KzGnz59/y0Lep/j7Zcf21kzsLRsP2e/w1ylp
lzDAm5d+KJp82w/sZvFpj7T2tMdfgLfe45iP7slBrwO79RcM076aLKoc2K1/H3GL3yR3jDzA
K46Rryo/I6ii3QyqkN6aidTmuiA5DPb5Dn9zbMKsj6P1UbQ2TA8BL3H404tghzk24fCHfolI
67VlQ3XW2DFfWfy1EVNxi01YvqA/ZB2Ue892LGyw+JulIxXJH+Fq0NAkO9P86RZ/s3RI2e8O
+i/la2bSmB0mE05/dfX5N7L460WyXeIDvLkSBQUwXYl6gvfKPeFSk5lIB3az2JNimJzzHuC9
cs98DZbkqdMA7xV8MRht2SHTA7ykb/A8F7iNyIp2M7LCV6yYzqy+CHO2027FweW1xd8UGypo
LUzkkMPROfcE0ZqU435aO32fZBPzvMC1alNQyobXLBoCvvL4G4EVt9iEdGOI03423+Em582X
Cb7z5JpZOkLhXaMxj0SSTtJdcuR/6fE3SYc6NHi48igk99ovi79vbfEH2JIF0IHefqwcG960
UAnwdqkX83tprRfgvWKPyTV6egTjCd76GwqGk0Cyj2WAN4u9Vrol16sBXnG03C4s/kZGRLuZ
36EuIZsSVc3acCxyfLm0+Jti47rNmmHtRsLZtLUdFn9TbMKbOdJVxKw1Sk5VrLL4o58+aT/u
sQnHF3SpR+jKC1raRG6JxR+cFivfpulwYxKt/t6I08pqV17hTw18MSQySYdq5FFbb761MEsP
A0/dnZfa+5Us/jib4PGB3iv6pJaWnsg8wHtFX0NfeJKtP0/sXsknULLplgd2s+Cz4gtC3uAv
wHsFX5Piy1ayuneAVwg+OD/O1ZESoTcDPISsmq/CIPmp4BWBtJfHuXNswq0PjV3/UyOm9HHu
Gou/8+reHJta4nxNLQacO3La4m+JidzpjMXHk/bjHpuQbkquXiO+AzB/nPvZFn+zdFiROkX5
1bgl6ySLLP4AzqdGZukQIUNkhlNHTFvzvBz+/vrQyG6HPyuYLqcc4L0KD2u+aDbAmxv2XFZK
tvP+AO9V8q0V1GSTyQBvLt5azEonz+kP8ObnUAtT9i88wEvOcM+9X3SkQ+i95A5s3LsSgPRs
Ftgq75d+XtabZdO0+bYTw+JPss/4Go+/fpqq8j7NRipHqFmNgZHk07ZoYuRqMFhHNsQtNo/B
4Gg3a901eD6X99MHg2fpcFV9mBViD/+kX2U2eJYO9d5bt5iAsd5fHn87Zd7XzAZD0WSc9IHd
rAKwQDZaYIA3az0tlO01G+C9Wk/9vmWnqwd4c80WSrK5/gnd+9fVG37dA7zk+Pbs++6r7wiF
0HuBHSi9ASn5mgXZEOlVOu+8gWqWjQL08Cozcn2UZaNLjm8vJoNn2YS+U2VDMkwqibhoRfnr
wuNPRyTELTah2Ji5icY5oaRNUxbpvDMR/jZNx7n4c9ar3/gY0MjqvBWth8BnPbvv83fHmvl+
L9wXNX16+3tOBv/2Fn+9Zs/KDvDmKgqV3pL1xgHeXs3Dnux1emK31/KAswr0AG+v5UHNKqgD
vL2WV7Mj4E/sEoV3PhSpIxFC76Z1qDZhih5CyJ3TbEjrmGXTOoKYYqtGWTKfHtYxS0aqqgFr
A0n30Cxy+OPz7D8dcRC32EQhr0WrIbRK/o9ZRfT5hbxJOlybKSi6MPIHOX1c++mFvEk61Dtw
NDI2zRdZX2W8Bfruqyz+GmDuJRzgzRJAIyUwKfMO8GaZ10traZeVJ3hzIY8K1eRQ4gBvL+Rh
zYr5A7y5mMelc9LzfIA/W+qNUAi9G9ghVqFpw3TDxg6pN8kmTtEqoxpC9kRikda7LOZNshGs
bMSGVl1L7izmXdn86YiEuMUmVJsKhUF1D1PJtJ5YY/N3UTeepMO+PQJwFenLICSNDDYEdkzf
HfPNHph/BqLm+rcu5tXPsPlLOiVtDrpNqr0lhzcLhPHXWA+Gjkx2AA3wXjkCrYSBVU6OHODN
sjiKwpp82A7w1rtcrRWj5OswwFt/Q7YwjUz70TzBW/9CiqjulpTFA7yil/FUSLpYGUEaei9I
wzr2iqrkgjLtfm0rhOTViPIcGyrVlVeNir0JJf3d/aIlsrhf9DJOsakuVbCiSxVBkqTFVZ2s
S/2pyHaxARtJGrfYxDgroD3NyVWSMZqzQ7B/rOjK+YjyLB2p4dQVdtHgdyc747HGjwbOzS6n
705vxL4YSa2mSQeLVxH0NzAg9G1qVvI9wdsPvKUnBdUA75V8wqW1ZPLzAG+9y4S9ACc9xQd4
628oQIUl6Q8/wHsln/qNyzo0D/AKyScXo6MjVEPvBB3UAtJIlYFF0kl9BdZEF19Ivik24UYp
WEOwiCbLun7NCjL9dN7jffrWuDiS2loMSJBmLadX9B+j2YXiG4kat9i4OuDqAglqQ/YHLj0f
saJySKdtgG/TdIQrdcDuEkksubuIq5bcnZ8+a7fpRLi6AD4q1TV5hvC7VkL/JhaE3LMnXwO9
va+sW/a7d4A3iz0pmC3vPbF7pV6NdIjkMvjE7hV6VYtScrpmgDcLPS2YdWQd4CW1vfNkOx0B
FnovwAIimouYMV3ai2sWkGmn0uhtkgxFPFfXqIQRQc2VW2hytfpTd+NFuWXy1jABCkqzTkBZ
98El/XP1VBl9PGg/7rGJ7sbKTdk3tmCQVkZLnLMfMaPXj9ptOqyutyordpRsJ61ftWBH6vuY
c6vpWTr+CTU1/woYUdbgd1aGv4Ter+M+SPnD0g/09vYyrsn5sAHe3DaA+b9wgPcqPm6l5vKC
ntC9eo+lQM99QQ/sXrVnLjEtOds7wEvU3oUrzUiv0HvpFcjySC9tzNnAnoIrBnNYzzry3ybJ
UCH1Vc5XYEweFNJkNsIfT3HpTE28T9+X8DJuLieAe/KUoK5xMsZTe52Ph+zHPTLRpUgKEiov
ega29jbW01PPt2k6bNSxm7/Z3ZqmQ39XCFc+nbt+n787Dah3VbVmadfsOUPfl9D7UtvBXvw+
J8soB3ivcDIr3bKJpgd4c6teLS3tRPPA7hXwXf22Zeu1B3ivfOeId0iatQ7w5g2GK3LLmg4e
4AUyAk/DyXzlHXkVei9LhFBrqxSOsjUp+HFJ9xS20xmJt2k2LiKcB2jn1tKmg7pARvhqf2EQ
MslGpPYWCTLILVmbXGP7XStdzCqPtIpbbB6RPy4duQkac/LlWXVsexrC8zZNh8NDDH1vRFIh
3ai3ZH7l0oxm9u5Yi+8okLGvma9T240a72uGlf1LAblN8IHdu8RCi/9mfiYjwJuFnkZ3a1bp
PcF7pZ7r32rJNf2J3XuPBYsl+wcP7GaZZyU+h0mZ9wSvkHl0XsXrI6Wi30sQ8UWqxvyof+Kx
ZoXREn+dK5k3y0bBlNSJkCQtKzeovFkyIo1RW++sWZPV6LBYoiN++qD9uMfGdYTEyHXvgMQ1
n1ExnrT/BwAA///sXcuOJDmO/KIRJJKSyB9IYDO/YjCnPez0Yff/sWSEKw89cC9ztVJZVR3o
QWMO5p3BkMJl4sPsqyQHZ8MR0e6/mMdoSctoYnKN5CCdK9JMh5O1cs/a4z0AKlP5U1M/nRfN
+07NwRYXLnCWcIA3M7ySMmqY9MRuT+Qx+gEHeHMqzzmbguMNA7w9lUcCyvkM8PZUHmf0Ex7g
JZXa8754HR4Ves+jgv2zkVCVarjcyZw71B2ONxmNczyPx291Fd1AOzjeZDA1pkmi7sxVK+zY
vITj5fMGUB0GFbeiibOiq/93m1pWqTDHW5L6uhi5nQ1HWGIaOnirk1ZYiWaN6uB5tXZ6dUzM
LxTO9IQzWMx7jdz+yrqD5C8+sNoxwJupniUT1CzuAG8me5r8xYyaxT3BW1eZMiczWKTmCd6c
zhP/o+DU9wDv/YRMya+/qJHNE7yC7NEF2RtGFXrPqMJv8WxWOZM1QhkFL5nCuCJ7k9H04lyv
qOQGv8kWsb1+KknyMR2Nv2QLNafi1PG1WcT2zuu2OmwqbkUTjVxUiZ2N+5braGVwhZ27k73z
1rzZaKRyqb7JnPQRgS6LqxJ69SKhNxtOvFyohPpNUbCe97sm9PgrdAfBAt+K0t6vrPBXjHGF
vwDvPfhLTw1UCjiwm+mnpU5oJu8A76WfyqkbKutxgLd+h+J/lFH3zwHe+gnZ7w1GqGDOAV7w
WqGLhn0dNhp6z0ZDrYqJ9lDMKWgJ1laMzVY5952Yi4ZDf4o9oKxZwBuWP7MicWrlghJMBUOR
Bq65CDMHy0Hl/VZks64s7HR4aNyKJlSvW1b/qarvtw4uzqLJEG7n4+az4VQqXEyL/7QLwbnG
JUbSOZ8rrE+vTm/sv51sQr3C5fG5maqfnX7+jeT9LIVvOMj3nuDNiR5O0TQNJnqe4L2Mr0qq
Cn6HA7yX8VkoQ6A2Igd4M+OrvrXACscA72V81S87CqpiD/BXM75hpqH3zDTUSifzRS6igia1
Vrgwhn3W+Tk8FQ2nws4m/Cj2iCpYmPCHVlzyu5wVZD8mo3H2VnKtzcmkWu5YPZbWcKSrYWAd
Vhq3ognyJq2V8PltuYNphUWUr9hFxnEyHN9fVGsP6Rd4uHIN5SuPScnrvXZ/dVSYwiCohFsf
XPx/Ub5FlG9zj1nJOamC1P4Tvb2sh9qBH9jNXK+GdTku7xfgzVxP/agGP+EAb/0Oa+HU0MHv
Ad7L9VpOrYDF5QFe8I4/P7L8BB4OEXrTvSNMxsTCoutR7cWyeytOrCsp57lo+NGY24yqcwrp
sO7Lilxlp3OJv7lograZqhOVLoqKH9Miu4ty0Uo4/CFuRZMT9VKzL44zidIrqpSyQm6KyoV/
4mw4vtEaNao5xq1gjz5ZEk6/aGSYDMeJXu1E0ihE3ODa/1Qu+cX1fh6Jv9DlB1NTB3gv4YsG
PFBA88DuJXytJFJw+GaAt64xZ0uKdloN8F7CRzn1ihK+A7yX8PUSKs0g4TvAX034hkGE3hHt
D+6WtfUe6RaGO9aWEL7Lcu5UNI9ybqdoQGCSjEWzqJ7by7nO7lw0MVeW1Zl48AmrqHnHCvpK
dOrJ/LnT3u5F49RNS/iqxDBt85cKSvhWiCAXvajnToYjnSqZE6RuBRf6W8H3zgd7PqajYW6d
nee30rLCdO+l6PzXJ0f2C/3VBqbWB3hzx15JHffseII39+xRalJvKP3JCs+eW/PBlGpFLaoP
8GYin1MG75UHdvMu1Bj4RXfhE7yARnA7q9v4wTusIfSOXL/fMfwXUjXXzkYNFfpb4mErV4mW
yWiaknKPYWxRWBpvxTW19FPRlI/paCrnUKYmYc1gj21Z4/l6njX63Glv96KJrJGvTgyj92YZ
dIiZzRr9uWXvdNLqfTqcsLlohVqjYgSKzi8bD75o2ZtdHfOLRMuS6bn4r+ngbRzvu4T+ioJt
8QO895Cl6HQHc1EDvJnq9cQgCziwm4mefymGfsADvJno1aSCyjke4M27kJOBBuUH9quJ3jCG
0Dtq/cHZyKKFqhY10OZiFdE71ad+n46m+QMtetdLU1SMKbUVc8562tr2MR1NpRzzmtlUUHHT
sqr7/6J4O3whbkXzTBd18iuP5WaKZr/W6MDQRZ/AZDjBvrv/ZJhKxWu3K6IpdhbNx/zimBM9
D8hjiTvfS9F5H9HbLPVXLTREwVzeA7s5iUJJVcGz/wBvT+XF5Q5O5QV4M8NjPwlBFj/Am5sw
LVkGP+EAb0/mlQ5WlAd4Cce7SLEMZwi95wxBVqT0HqpyYEdbWeKLWuR0xPN9Opim/g+3qlwJ
NZZMbUU0l7m8yWjCFcJpRKEHC9+Zy3s4/l5vtLd70UQuT4mJVUh6xeWcl4RTLm4Tk+EIaZfs
70YOqwtY/eXLc3mzq6N+k6+1V/MrBdjp8Erm/dpSf4q25g3wZhpQUyaw9W2AN5M9DW1ZWOnP
sXupnkWPN1g2GeDNybwe48hgLu+B3ZzKazFDiObynuAvJno2zCHsnjmEkwgiYuZac0fTX2uY
np27KcxG47cSy1St5pxRsc20YtLoMpk3G031S0I1eRjXgo15a5J5xeyHO+3tXjSRlis9i1Lz
kApMjZYk84qddU2+T4cjHEUO32lVrYPn0TJ7tvPOvOlwMhVfH/alzwyXbX/PbN6X6PwVVH1t
SaVk2YTIbqW/qMyBegkDvPnsz6nDZbwHdjP7NL+1oXmBA7x1jUlLKmiqcYC3focP8T50JH2A
t35CdtYraMfAAC94rRQ+LyfbsK6we9YVj2FT34nFjzWwjBQPLYjmajRkLpqY8qhOBYVZaoZ1
X2iF7ovqef5nLpoY663drFqvkkFXvw1SfzaMK25FE1J/3LSGh02Bff3ymkmXK92X2XBiBNi6
E+rSWcFi/zKpv/NZ4OnV6dVvbo1Uul/j4PvBS/dlFdP7Lqm/3sFUygBvTkbllNGU6ADvpXxV
/J0Lqmg8sZsJn6aCOqA9sXvpnnGqoFflgd1L9mLNCMyHDvACQuGb+fwIHs4Vds+5QlvTbFS4
E+Nkb0W33ZXI31w0nIrFUHhhpZ5Bqwcne0uEXy7mgOeioURWVbK22gStr6waAz7rTvvcaG/3
ggnWZuqEght3qQaziTWyzmfpuffpcCrn3mvJTTpluBNyTdX/x1vt/upoyX7hi4lpQYV+X1zv
l9X4y2ahmQAmpQZ6e10Znlca4O00z98BYB3oAO8lelbDYBdV+XuCt36H/gZNHaTKB3Yz1eup
drBSMMAr8np23rxvwybC7jl4WI72way5soAnlj+0wnLtSuNvLhpnbWZas9OJ5psWpXprNP6u
qn1T0Tz0nKmHR4Q2A6fj13AjOg3mc6O93QsmJ2pa1VdHizNJ2yrx9zD2vt5pt8ORJi0UJWOG
VsBu4nhqSWH5fExkNhx+6Ndw8x3XGM5SviT+llG9b5L4K6nD9hMDvZfxVUrN0C6uA7yX8YVy
XwUF4AZ46zpz5qRoL+EA72V85K96Bld5gPdyvtZSSHOAus5P8BLOd9HjNXwi7KaHh0q2Wmvn
mBH+aWq5U9GEzF+L3JSVnFGfmlUyfxdWWnPRkBMethLWYIV7BcsZa1gS8Zk+z+dOe7sXTdC3
2p0p1VJiHB2lFV8u8zcbjnQqnSmUGMOieq/O37mHx2w4HA4e3VquYgUcIHuRvl9U6K9RBtVf
DvBemhcDv+AHPLCbG/YovGzh0WDH7qXyWlJVNO14gDenbs2Z743J4ABv3oM9tQam9QZ4Sbve
+cCmDXsIu2fdQb04K1K/abSMy/wtqeDqRVpvMprWnTiKOJOA7RQWyfzZqfbxx3Q0lSQq0aIx
Z4FW19c0hJ1mjj532tu9aB6Zo9xyNpFeUZeYDaPBs+FIENUanYcxTQvn9b56NHh6ddSasP8m
TdHj6zUZ/GvL/Pk1GFb5c+xmEuB/s8OOvE/wZqLXkwhqdHeAN1O9nojAksMAb27GjNYAVLX7
AO/9hETJBONFB/arid6whbB7lh3UTJvGDV4znMtbQ/QuNGBmowml4FbIuUSw160aMFdEbzKa
Wqj4XYuZSwcdAeOhJb16P9xpb/eiCcrGXbJGKJVAeepVRK9e9OpNhuPXCYo4qCsXMNO6Qedv
enXMF8dXppmp4bKFv+Vk8G+v82cGqtQN8OY8CidVsCA6wNuzef5SASnUAd5M8ih1VLxkgPfn
8zJqFnyAt+fzKqOO0Ad4AZW4UnO2YQ1hN207NO7wrK0ZngH7ctuO2WiaBjHyy2e30tAM2Jfb
dsxGU/1+5atSfHUYbqH8ctsOG8YQt6J52HZQryH3V0sBtYZ25PMmw5GwFq4UkxlqjNY4F+Xz
Lkq2s6ujKvK47sXMN1yyfSX0FtC870noceoZnCoc4M08oCcWVGvlAG9me+r0CG3QO8B72Z7F
LxsVvT3Am1N6PZkymtJ7gjen9GpCycSB/WquN9wh7K5zRyaR3EwyqsC2iutdif1NRtOieBsS
eY0YzLgucu64TOlNRlOLFM65VH+Twa4qS1J6V84dNswhbkUTrK0/UnpFcKL35Up/k7E8lP7Y
WXijhtZvduTzZpfGTPxnY/Ee6HBv3u+Zz6NfXunv1jgBOEiw4A25gBZ/j/5gS6BYwBO6l4jk
Fr5lIFU6wJsJsSVUzefA7qXDmSVlVHHgE731O3Sq5BsLrMIP8NZP6HcE/6PgLN8AL6HEZ7TL
icpw07A7Dgf+E861+e3WqrNJUK+vbZhSnoqGnXap5taddOUKFlJ5CfEqyheUeCoaSjVyn85U
nKeAwcQzK4rc+aLIPaw0bgVTUim1VmVu0k3Ru9cK0U7i0/Gb98loQlnGuPpNvGV6aIJicjQr
KLGcpnI/pqMRv0RS607x+x0t76nF+dkp8d9KejAXcK5vgLeXuyuqQzzAe/leyMyg1soDvJnx
VV+5Cv6oP9Fbv8UYO26oweITu5eRMqfQCsEY6QFewCnoNM32Xz0fnhrxf+7wPY1pAu1USCpY
Uo2HlvC9s4Tu+2Q0Tt1azaQl2guqYlOj/tCSFGg7IxUfk9E8Ru9qTCj31hlt//CHVhA+Pive
f+60t3vROHdjczIRLdJSYWPpFdKn9JBZud5pN6Nx7taycFdzMt4eo0sY41uhSlNO+0Q+psOR
1nPMsGlpJAL3aE79cl6M79sFCEvOyV8r4K9woLf3lKmCd6kB3kz2anBgVIDwCd5M9qympqiN
8UDvJXvSnQWjgjQHeDvdy6hkzgAvSe+dWj70XAaluGMq0FNuWoyc73URwwiSP7SCINXTfsD3
yWj8fsdh1Ed+h8qothYv6Qe8pntT0YSSAUvvvkIKTyvHQysYRT4VpBnRvN2LJiezSsrVuasQ
K9p6mpeYi5wPxk+HI9YrS8slO0EC3/nO91aEw3TaSTsdDpv/cNivFqV3tD776m789VUI/bZb
UcYy0Juby8S3Gewl+wRvbhsoSdBq0gBvXueiiQvYy/qJ3kv7epiwgTpJT+xe0qc9DmSw6nyA
v7am2zMNYnHHXaAlo8bipLQYk2ANTv7QCpp0SfqmonH+1luYMyv5eQyKNUclYAXps9NS23Q0
YTPbpPoZ3xs4QBUPrWhz5FOJmhHN271onL6FnEvWHJ4pFS3qrrAPokfR5Xqn3YwmrOGYxVeG
yCnlZkO5etroOB2OCGUzlSxNcbu/uXTAi/N9swihFLB7Z4D3cqho04INUA7w5s49Sg1VKxjg
ravMvUaFCEx7HOC9XF6cRoAJ3Ad0802j++UBVcI8wCsY3ml2ws9dHizinn+FM6KslQujd3l/
ZEUs9aqGOxVLSZ2DEImUkNlB80Z9BVs1Oku4fkxHU2O4oAlJzhnUMS6LmvZOuffnPnu7F00O
qXWLGqFT4YL2kOQlM0YXjOh9OhxfGr9FmHS1XDJaxF0yyfKwj77ea/fDyWGGp01JO5yilCn2
/eJ3P4MEYU7R3gxOLD/Be4/Y3Py6jsrTHeDNNK8nQduPn9i9JE/ZTwNQ0myA966x3x/UUKHJ
A7yZhsaYKzh3OcBLiN7pxHLPMujEPdOK0P+l8JEzZ0ggdfWHFkTTzq29JqNx1lb99PX/cLEQ
2kCp3oq1sVPZvo/paJoveH0YuDZieP56yVhsO1WnGdG83YvGSZtyyDLn0KhBDQ3yEukg4lNu
9D4djsT93ClrUcroibTKRa5c1G9nw2Enelab5Yev85eK7by43neLEKJmDgO8meSVVNA81ABv
z+VxueEpEuCtqywUFzEs2XFg965x2KwxOnR4gDeTvGhuQ2eDDvACIkGnc55+9NZBJO5YCVD8
hLMIP/qmUGK9ZPa+1NO+//fJaErSzmGOEjMZBaw6xUNLSN6pU/B0NB6M1ZI9loK21aYVClJE
5UzJ5XOjvd0LJjv/zpFkrU7utYE6CvHUknTe6RDudDjSIzEpGtk8AlPH/tQKynpZr50NRwqF
yU8LyYUKe+C96rULON735PModUX1pg/wZqrn/DKDef8B3kz1NExXUcWVJ3gv1dPw1AXT8wO8
9TvkLIkbmC8b4L37UJu/tlHd8wO8guzJRZ98G4Tijp1AmOrW6q93CzE18CK/yFT3oalzdgRP
RUMpeCsJO6toBUyrx0MLotHTbOvHZDQlmS+4+XssPwz+QLa34p1M+epa0QafuGdcoc7ui1Tq
2eMBVb3iqRUZPT6VIZwOp4aeovna5NIq2Ai6SHOF7WL6ZzYc32Ycnbrdfz9g71aeFLz82dke
f4UMIahssqQvZtmcyHfI/WF39AO799wvIXcMujIM8Gb+aamhzGSAt65xyeGni6qXfKK3fot+
6U3WwI7rAd7LkWuLdgqwLn+AVzDQ05SW84I+WM4dp4MWDtqNsuYYQACrsG2JzEippz6s75PR
ODWW1vwAda4eZn0on16RPLWrlq6paCixX08blxqMDVQoj4dW1JRPRVM+d9rbvWhKytY1+hKj
uxNuhixLBG2uxkOmoskPd+mqJpxLRi2u1oyHOO394Va7HQ5rzVmcTVs0OqPpxtdI8DKq912i
f62gjO+B3cv4Qj1NQOo+wHsZXxW/VIKDogO8mfFRj+EPkPA9wZv53mPCBxTUO8B7+V6PNjpU
Y+QAr+B7p4YHfgrr4BR3DA9aajXX3qj3mrmikn9tBUOS0+Hm98loOJUe+Z/aCweNBfleWVNe
PmNIH5PRUJLiNy4pWZuHg2rAzLXw3+F7OijFPQ+X4rTImVcXZgNz2yEMvYTvXXSrTkUTzK2H
XVAv0hk9M/MauSG7mjyfDEdy5E+p1VaLgDel39X35G8g+ZdNU1XUHH2gt5M9WLZkgDeTvZrI
wNLoAG9e5978eEMHlwd667dYi6XMYK/eAG+mezWhjssHdsFb/lL7xQahuOnnETtQqvNIooaS
vSXaL5f6zlPRhDVHzDpY104CNvEv8vOwctHgNRVN8DY/ebk2q7mDWgg06bJwR/DPBp+4Zxph
3ao9CpjZr2doAXNFZYGKng1uv0+H4/vLfzalW7R6glo2s4rI/8H2Li4Wk+GwOMnr7EvEflNC
w5n76bzY3s8j+CfxzoR1np/ovaQvmvBQdfsndi/la34lhQXrD/Bmyqch4AdKZRzgvYSPNErx
4BDTAd5L+EySNPDqMcBfXM8twzai3LP06JWp5cpOJ9GRnbakqf/Kwm0yGk5OJSQa8Mxvo2Ad
gNd4NKucU765aJy9Se+t5lZZOviL9YdWtOBdUb4yXCNuRRPkrfracCcKXzq0ZGgr1G2cZf5o
q90OR5zs5V79FWmscDgr5kec8v1wr90Oh6tvsd5avAZqgynf1GvtRfm+We+vdnB+a4A3N+6V
1A0VrDjAmxv3KDXwfDmwW9eYe4wKoDmPA7yZyPurvYIl0gHe+wkpp9zRXXiAV+T1LsZGyjCL
KPfMIppfNahLFqoZzE74Qyt6j6SfJ1vmoimpqZqfuJmkZnjQoi3gEcXPxvODdzKa6nfo3CT7
sYu6VZY1gwkk50XcMqwibkWT/U2npcdv1V/JFR2zWCP5dyqc8j4djXCY2mYjzgVt2ZuTTflz
MHKuODQbDBubU1XJuViFbYdfLXsrGN53Kf5ZB7vOB3jzEat+v0PFYA7wZqLXE4Ot1Ad2M9EL
x11wgmSANxO9dqMn8wBv34WFwG6wAV5AJsppl7kfv8MgotxR7Se/qzmRz63nGrYKINGrK8pQ
cmGjNRdNSCu2rF2p55bRXpQlonLFTkdQP6ajqaIcTZTO8lDBXX9oRTaPTnOTnzvt7V40wdlq
uM+RUljFoGrISxT/il1k8ybDEclUqHZhEeavtbv4Uzhyofg3HU5urbEvTfWowOm9l7rzL6r4
1wws3Azw5mweJYUzPQd4ezYPFS09sHtJnoqf0aBMzQBvJnk1aUHV5w7wZpInyRraN3WAV2Tz
TitPfvQOl4hyz7+jZ2GNWU8j9JcfDy2I5srBYy6akjpp1J89oALeBBcZeHS+yLFMBlOVcilO
jXptaBfIErs5Ku2HG+3tXjTB1nrJIWkjlUGN6rwk0UqZLm4Tk9EImzNHbaI5Kzi6vobiXU5k
TIeTi6+LdLFqGZZjfE1krKB435PO4xjwB7N5D+zeE5ZrODqi8xhP8Gaep0kZFCQc4K1rLFn8
/QlWgQZ47yr7FYI7KqZ3gLdXlguu7fwEr2B6ej6PUYZJRLln4OHfnXWi5jSyZywp4Q+tiKad
kqP3yWhC2Ziakz0uxgK2/K+RQy56yls/pqPxRanVd7hQJ3hctS0Zvs0XbaDDIuJWNDl2GlPm
Jk6NKpzOW7HVLg08ZsORlv0+YblJNymwV9saA4+L5rzZcOKHU6rE/xRs0P9dDTy+RO4PdcIs
S3qFl82J7Bb8q6k3MFE2wNt7tjoornRgNzNQS2HUAAv+BXjrGoegRDJUq+4TvfVbFJUkFdXE
fmC3fj6uUewDGegAL3itXI6HDAeLcsdWIOT+QlFOKMQfFGOg8dCKXOOF3N9cNCH3F8olpfTo
tcNYQTy0goHqRbJxKhpKXClc5DI93I9Rub8lfhx67hZchoHFrWhC7q9x94iyFoKdX75c7m8u
mpB/Yc6le1A5BLQ3yv05Ab3oXZgMh7t1LmRhvZhhf7+5s+tnJ6B/K7k/UrCMMcCbc46WDMyL
PKB72V6NyU+0DHSAN7M9otR7h9X+nui9bM+qU0zsEx7YvWyvEa7yM8Ar2N6F2F8ZFhbljq1A
S41CYqRaya0LLPa3ZE7kQuxvLhonbiFMFVXlLhmsk8dDK0rLF2J/c9E4cZMaUoy5NM5odnsN
27sS+yvDwOJWNEHcoqfTDwyuDRytWMT2mM9uSe+T0YRsH3dqzcKaB9X9XCP2R/n0mvQxHQ6r
aetUIsVtsDXea1JkFdvbLvZnqRBooPCJ3l5cJn9lwMXlAG8nexWUSjqwm1e5h+0rmuce6K3f
YS2cCoNUaoA3k72ahMFumwFeUVy+EPsrwy2i3HPyMMni61yd6xVQvyIeWkH2rpRfpqIJdU8j
js4uM387oWJ/S+wV+Nzfay4a520tXPHMGZ8w6mA0KcZxR/llmEXciiYGC1tRc+7aczMwi7xM
7O/cOXg2HGlNnbxG42rz68VGsb/nEXi9126H428o6c0qm68PKGoVT73Y3iK2901if5xyA3fv
J3pzrxk5TQIZywDvJX2tJFS99MBuJn1KCc3XD/BeykeSUD51YPcSvq6pP7xvoQHrJ/ira7nD
LqLcs/Lwt3vv2TpVJVBOzh9akQ+7JHxT0YQLW8nUSiUTEyyaRdZtl9m9qWgiu6fCzo4sk4CV
6VXZvSvCN9wibkUT1C1byc8WPCdKOwnfQxHoeqvdDse3LwtV9gUinL+ukKqgLBfF3Mlw2C+l
vVCv/uvhDHu3vdSd//rkyH6pv46OZQ7wXooXSZwM+k8M8OaWPUoN7TYb4K2rHAZiHbQ0P7Db
i/RdQBGCAd68C9WXDR0OPsArsnpXUn/DJqLcs4lo/l/tmSU64AmW+ltC8q5SLVPRhJhL7kJF
LEdD1U4FmC4XqhyT0VQO6WPV4rQINE4va6qEl1J/wyTiVjQh9edEWHJzatRxebxFWn8X3QKT
4Qg5ZbXmdwrRBspKLlP7u6jhTobDFq8X9ctE6QbKDb1quL+y2l9JGbVDG+DNPMD/qIC5ngHe
zPW6X3PQbrgDvJnraYLV/gK6d4VFEywCo0vG7W5KwLQK6/w9wQuYxJXOHw1nCLrnDFFbq9or
s9UMjhOt0vm7EHSeiyYIWwtRN9Ma3gM7BZ2tnAs6z0ZTSVp3GhFeF6BVUVnT+U/yw532di+a
4GuSrZJ17rWAnoCrWF49zxrPhiNC2h+TGRKdrj+LCMx0ODnicJLXq7YOZyZfIjB/neVt1vlr
2RkbmCgb4O2pPBUDj9cDvD2VVzrqx3uAt9M7AQsMB3YzwfMvJYO+IgO8meT5vQHUKjuwKxJ5
p5aifvAOXwi66dnRKJq/slm05qCJvBW154c4y9m5OxVNSU6INNw6jGsWVC1liWah2nl73mw0
tUqrUrqaoW6UG6ScaRhD3IrmIeWsTiLYLyqZCe1nWyLlfGXaMRuOMDFRVnX+yDgn+mrbjtlw
2KRZ7+YrX4vA1dpXIm8Bxfs+nT8wTTHAmxN5PQmBQ+0DvJnpRS0bZnpP8F6mZyUa8FEL2Sd4
e/clqjV1YDfvQkqEtl8P8BKud3ECD2sIumfb0dgJhSqLGqGOc2mFTco115uKJmhbzjFx64xP
cEnnFVyvn5Y5P6ajqY/ZBV+bbhkcLImHlnC986EfGsYQt6IJdebatJP/K1eG03krFse53rmk
5Gw4vr96i5l1/3fBdf6WaODQxb1iNpxCZLWEGrq/79HB21/TtmMfk/ufP/79x//98e///tc/
ir+Z8j/++b//2npSYa/A3ZML4NDCgrfyAir+HXKHjSRRBY/jAd6c7IouHJSjHeC926yWRB0d
QDnAe69bmVNHrZIHeOt3yA9lJfCm8MRu/XwW4/boBxzgBa8VOjXjdXo0/DvojqlCDASbdY2W
tpjtRKeIV7iR1HJBxKeiifqF0zw2KqYMZo5oSc9I6afXio/JaJp/MBKrvTTSDHa2tiXRUD6V
jPncaW/3oslJc7MYX8qNcgMPGX9qhX441bNb0vt0OJW6qN8scufOBa2rr1HA4fOZ6LlwShLT
mCyzVk1hqfr6KquvInrfkXhtnBNXcE5hgDeXXzlZA4dRB3gz32upCTpVfoA3873wJAHZXkD3
rrBSElB578Duvcr24mcQeHkc4K/mesPAg+6YKjwGiJXID6vSGeyhXDRALP0iEzYVjX/RmYuw
n1j+g0I7mP2hFQX2i3HouWhqqs3/Ib9uxbwfeDdb0t96zfWGfcetaILrOdvzneZ0r6HhLOJ6
l0nXyXBENHcKgUBxDgsX2JckXS98uefCKYmVM/sCacnoGFN5SVsv43p7665WgqeDTS4DvL3H
TloDq4AHeDPJc2ZZQD/iAd7cQxFHCEjlB3hvUo85sRRQSPAA703r9YeNFvYdDvAKqtcvqp7D
KYPu+X60LrWrxLgM2q/HS2YYnFyeD0XPRUOptNojLyHi/Ah1BSwronnMs5wdv1PRtMS5RgbM
GUVuYMnTH1qSB5OLS8UwyrgVTU7RtOt0r/XGhRQel1nio9d/uNVuh8O+1WL0vrbGrcFK0Gum
fy56KafCKcn3WVNqLZfoTgGp3lzf1Yvq/SRKh1Z6YsYy0gd2c5+dJH8ToSqHT/DmXoGc/KRB
ZQ6f4L18r1NS2Bz7AO/le36VoAK6zg/wXr5H8Uc7yPcO8Aq+Z2dXej+Fh1cG3XP+qN2qFFPz
jQgyWH9oRTTtVK/tfTKaaP2VXnqOqVUDhbrLGqHufjqB+zEZTQ3PTX+BdZZm6MRqOIku4Xtn
jOJzp73diyaYm0g1dhLrtx+4Y28J38unNtDv0+H4DYla5tpFVMB3waw0IKxD+TEZTgk127CX
Nn8fKFiUjodefO+v8r3NQofSJXUFm7gGeC/LK+KXKfAsGuC9LE8khQQ0ODPzBG9dZbLwJAE5
1ADvXeUcBmKokOAB3voJpdTU0ALuAC9gEg+D9bOzd5hk0D2TjMykWnOhruh8dF7TqnfuFzsX
S0lSgt3RY9AEniiea/z/M8fjC1mSyZVRlUzShGqIc4Nrs+JWS1QvbhPDIONWNM7WnHx7NOzM
lQ1u1VvD8S6EDmfDEdJczFowcNCwatV49I+32u1oQgXLl6VSdSYONx7O7bUXx/t+nUPRHNU6
8AA7wHtJAPdU0JmHAd5M9TQZ+BUe2M1ET1Oc6yDRe4L3foMavrcgnR/gvQlHa/61oLbEB3gB
nWC9SLIMcwy6Z46RM0vpVYqzJFCZlyav8f+RzruoqU1FUxLFWUVU/NwqoHFJWdN3aKe9bR/T
a9P8gmCNnEVSRRtXl8gUXZdvhzXGrWiCtJUStojMvfm9YivVOxVvfJ8Oh1WZqUYSPDoPv1Q7
5g7XmwxHnd13v1q0h5cgGs6cRtqL632j2qH0mjqczntgN2fzahIDBwQHeDPF49RRobUndi/F
U/MzDZxkeWL3Z/IIXeEDvD2TZ9gJ9YSuIHdXtdphikH3DEucupOfTlHjVDQ/7g+tyOO1Cynr
qWgiJfcwIaauFe3p2JHHm1wbNY+m5lysMFh5joeW5PHOrXFoWGLcisZpWu7mm8w3m3EBuWpe
4o1zncebDEeoRyq6Ze1Wda9hyY/32u1wtAvnh6I9E8Ph6NRr7UXuvl/nUJRTFrCaN8B7OYBk
Z5aoYcQB3svyakwhMzpu+wRvTuW11DqqFXmAN6fyasoNrXsf4M2pPL9AoN0NA7yiM6+dsz0e
5hh8zxzDOpdWVbuyGKqmt4S71ouh29loiLOqZmd7ueGpvBU1aONze7q5aEKFMrNKSEJ2Q+0a
/aElbO986JaHNcataIK3SRRWKFp9FNSLWcP2yqO2cr3VbofDyoXCya0X50eo297cmCo8Ev0x
HY4W7WFC/HAuAa8WkQD8Hdkew2zvxqEBDpAuEZFdNiCyX+AvV7BENsB7GSi1JBllTwd4OwMV
AeUzBnjvPYM4+b0fvGcc4K3fYfOvpSioBT7AWz+h1h4JTuw7HOAVXYMXHfs8vDv4nq+KlmYa
jsJ+WQM77Wjy4PlzMZnPi8lz0UhiKr1m5wS1VpCBxkMr8o31PAc0F01Nzbqp/wZzWC/CsyEr
xKkf1lrXO+3tXjThq2LZiXRhbcwwZVvjq3I6PPs+GU7YsZb/BwAA///sXVuSI7eu3BEDIF7k
Bjriqve/nwtIxf44jqpB0Wx229aE7TgfyTOCWCom8chs0ru/fPz+lh6mWDEacqX6MhsNGfmu
sHS2bEs5Tg42/3b++d9S+KvJhuQB3kv4JCTGklq6A7yZ8MkdhT/5AYU/hFJ7crx/gPeWbtVP
LUoWlwd47y4DSemY/Ihf6BVJxwulPxoWHnTHVsF/JNbU7x0G3cByuQZftCIaPhVMeUxGU0vv
NUKpzCxJB9tYtILy9XOlv7lotKiI9Qo9GgCShQxd0z94pfRHw8DjVjSh9NdDuLD506Y9edCs
UvrTc7fk2XCMIlMfBsNkLZmG8FVLxoGvEtxT4aAfRU74CFo3lbQJ5dxF9s35fl7pL8Z8ktm9
Ad5cX/ZTk5J5nwHeTvaAk2W6F3Yv1VPyAyT5Yhrgrd+gX5hLzZqqDvBmqqe1SJrpvcAriF47
o0Z+/A6LCLpn3xE+emJVoTIlq8u0xkdPLsQ4ZqNx0tqZqh/CgJxVLVxirdLpguhNRaOlyXOo
QgG1Qu4XG4uWVJfPqMTXk/ZxL5qoEzdnwyH94rwoycJX6fxd9BJOhyPWRLiBcYV0890aGn5h
FTMXDhZUDatxJ62c/eXgpELmm+j9Jp2/5NTtgd2c2mvFIJmWGuC9TEBDACrr2HqA9/I9qwVr
Ml0/wJtTe3E2ZMfTD/BmvtejCJpteBzoFYzvYnqEhlEE3TPxcC5K0eal0gCyjG+FUQRyO2MV
j8lo/Is2Z8UIziks2bBQJzvg/5LZOxf6mwvGuRtKE/8XRC1ZaNclhfZLoT8aLhG3ognqRgaE
4uRVsj1Diwgf9oti7mQ4fl9B5mdx2v9XdpR2zuHsDuGbCse5W4+RbQDusU9ZwjeVE38Tvh8W
+tOWHRo5wHtpHna/tSZP1wHeSwCYSraX68Bu3eMoa0tLXtsGeOs3SNhKvGqSYs4v8N5PGHMq
kHSGHuAFPIL6+dgmDYMIuifab/5eF+ehzK32rPyxLRkZ6RdJvaloaqmh28tir/8mOd6KpDW2
0wLh53Q02oyUneepQlbxquiSAWG4SB8Pe4hb0YQdLVfU6KU0hOQhs8jEluyPj9rtcDQeMmwx
MGKN0km973XR+5wOpyGCtm5U/YqU1uaZq62/Sd7vUPqzrB/vAG8u4HJpmh4QfoE3c70W06Bp
pT9ekU24NR5shVr2GzzA29O2mu3eHuC9KUenwK0lT98BXsL1LvqnhjkE3RHsD9G+auZUApx6
ZS0QFyn94UX71FQ0TkI5NJ1b4ygRZvuNVnRP+V97MZwxFQ2VyONBDIUD16TwEE2aZ90p4A5r
iFvRPAu4YuKR9JB1znK9NQXcqzmgyXCErGs4AlprPR3OityIc72LZoHJcPyyF2164o8bi2ap
61yz/pvr/bjSXzKfPsB7CUDFApasig7wZpJXi7W0nvMLvDmlFwq2Sen8Ad6c0rOn2lkypfcC
b0/pMSVLnC/sEpJ3cfQOdwi653Xh97QQ12Xu8BRlydGiFelJ5Yssy1Q0kZtTgh5mcy07dFTX
aMDYKQH/nI5GeyewaEKVnpbaXjKB+2zruH7SPu5F4/ymNugVY+K7Y3JmbVFCr/JZOI/pcFRb
FKB7q6QtOR+9I6E3GU5DwNibXtksaUn0Tuj9sxX/0JKivwO8OaGnRSTJpAZ4M9eLirFkXdpe
4M0pPXFylKxsvbCb99iKX/qze/wCb07oQYFkpfPALmATeNqW4+fvMIege1YX3dgfP/PDyilF
2rl2SXeeXRy/k9GocEduZq22pHNtLPrudN5UNBSmKgIKgmicjIaWpFpf8xLXT9rHvWginVcZ
QGJUlXty3GqRtjO2c8vn2XAEqar0xiz+tKWJ65I54qt03mQ4nVCqmpifl2bZ0m3/Vxp3fIva
HyZvnrhE1WDZoMgP6P3lTqEXdHPjoBXDpJHpC7udeXZNHnsv7NbdpWqFOSmS/MJu/f60U/H7
e1Li4gDv/YTg79ya9FUa4BU5Rj5jN84HhnMF3XOuwEbcpPr1rPvSZB4Ll0i+nI5SPCaj4aI1
5lxUm1JLNnXyEmVmtNMp7c/paAAs3Eq0S6SyktGseBvXp+PQ9ZP2cS+ayDE6fW7URKFa2k93
xaW84ilVe0yGgyUyctFtK+TXg+yVDZfwaDgri39Ob44fQgA9lD1ibidNPKfu+7+deP6nZP4w
q+06wHu5HlHpkh3xO8B72V62X0n2+sYxtkItWSwY4L0sSuUpNJV7+g7w1k/oFMLv1smnb4BX
8LxTjZT/Mx6eFXzTsyLU8DRGi6kmmdGaeiUKnKd95qLhUnuo4Ak7nUjqFMaaFTTvVP74czIY
KUEgkiKcZcUvwNnd+T2Ch0/FrSCi5Erdf6B+k3B6l7z9rhJGudBwngsHo4cz5nVYuSpk52SX
9HDCn5+w29EQ+tnoRBVC2TObkKd3/XgRudut5+dPYrbNfYC3s7qmyWH6Ad7M6rgYJtnTAO/l
d2CFkrfoA7v1G/SDstTk8NmB3fv5gIoI5bIqA7yC27Xzmh4PNwi+59Sh4V3P1MEkO++3xo8M
lc+1Xeai4dIBuh/pIUPNNevU0Vcw1Wer2NnROxmNsAlyRSerlMxp+6IVan6A5+IuPMwgbkUT
pkTmF9nunKgJptVQVlimX1jpPqbDaX4Xqs1vv8CQ7xNsa5yBz/sEZ8MxqxVfI+aYLPDApADA
m+b9JjW/pCjtgd3L9cLKLJ3BO8B7uZ6GX2K2U/AAb91jf9WGSFhSze8Ab8/lYdbdboD37jJU
CX+LrJrfgV7SL3hxDg8zCL5n1OFUhalG3VazUi+0pmor9bxqOxcNFydHoZyoIerHOf7qi5aM
/7bzUtpcNFrIoiyIlbV1TnbRrPGfrRfebDysIG5FAyVcR9Aqhij1c44mV7VdMs18lTieDMf8
iHGC1Pyy5G+gbJ3Tlgy6wNl74HMynKgnmxL4/zVpl2RnW8F/pTnwv17OLywf03J+Ad7clQcl
64X+hG7uyaulS3KiZoC37rC/HdJdeQd26zdINc7prJTfAd77BHYqJMmc7QCvyOidmn35qTs8
IPieLj+rQOOq1J+SHqnXOq8YB9GLacy5YGpxYsehoRsSL0npaV+0IppO50p+s9GAVGDt1XdG
s2pHvmhJZfAidTwMIG5FEwk96BztqVUZkroDsWpFG5te5I4nw1G/F9WG1kGgt3QVeg35vkge
z4bj9A6aRHpSe/J0ndXeefO736Hk17M9Wy/s3iO2ml9vkxWmF3YzzTNnvklX4AHeS/NChrln
B6cP8GaiZ8U0V3c7sHs/n1mp6fmVA7yE5l2cvsP5ge+p8RuSSVNE4JpMFcWiFWm8U4uRx2Q0
TtmQQyPOWkdJdhnFohWF29Mh5s/paIRjGLMjx3RpluctKdxeCbzw8H24FU2MUTzlgFs8bWki
sUTfBfVcSmg2mpB3Ed8Z6YZS04LNK2jeZd12Mhxr/oryh8x/O5aneXMjZW+a98Mifn6tT7aB
HODNaTy/rPZknn+At6fyOOuxPcCbU3mt+PspmQw9wNuTeRWStusDvD2Z1zA5mjTAC5hE5QuW
N7wf+J4vByv0Gg61Grf4bDZvjYzfRbF2KppIzAmTOS+iXPOpr1hRd+50Pl87Gwqov8H83K3k
/yRfeYua/E+r6F+P2ce9aKD4rjCrf08eFCd/28tSeRccbzIc53hRcjbQGOnO/WyWpfLOLkef
8+GgcczWEnRp+L0+yG+O9zs0/DjZIXtg9x6wMVYhyY7kAd5M9HohTas1v8B7iZ4+1cGSRO8A
byZ64F9LUvNogLd+Qgb0Ww4kc94HeEk671zhgofxA9+0sVAwacLmdC850blIr5lPde8ek9HU
gsymElO2mr2y1jVdeU0uciyT0WiH6pSVojM+2S69yIANTh3Lvp60j3vRhB8FgwD3l59zOp+3
ZHgYLu4Uk+E4MTIg7q35DuU9g5cw8dOxks/pcBo5A29GtYenc3Z35sZKfjvXq9+h4pe8rK0Y
2Ls1SJAcIVjwilzAi39MWZCSL6wB3lziDiH4ZGrjhd37kAkWguR5PMBb9xhDdFGzbn9f6L28
mEK8KnnSDPDWT+h/YdiiJQe7DvASXnyhDTK8MviOf0G4Olt7Klxrx+RtqS1pmUOBi3bGqWhC
/NBDCa9lBW5ZJrlCg/R6WmUqGi1+DwLT3v3Wku3u1cIr1K3BLm5gwynjVjRYumDtGCrqWikr
27JCGSFSyH960m5GE/V3Z6egqFQrcrabcUnVHurFsMrk5ojAc5aI4lWVPMAmOyp+Oyv+b0kM
clJwbID3Ej4OodWkDN0Ab6Z8Gtp3ST51gDdTvtpL0+wM9UDv3ecmhTDroHyAt37C1qWAZeUG
D/CKmjdcHMTDNIPvGBlYVAvIwpxUNTuSE4uW1LzPonlMRoOl+fHLTviqIHK2gr9keNxOZz4+
J6ORYsgYDaBh5ZwLRpY0nV4zvuGYcXNrnPFZlYoxZJTOuS9hfNgucu5T0YT4RbX2JH3q5C87
nrxIX+ficjG5OVyBnRgr+amU7EiIRW/Gt4bx7dcdlKxD8QBvpnq1ZFu5n9DNNI+KX6myNO8F
3kvziDXE5pJ57oHenNnTAllj9wHeu88Qee2s8PUXeklu70IfZHhU8B3jgFZMmkmkCwie0jCp
3N6amvfV+TsVTeT2FJDQD62k2tKqzN7pDPnnZCz+09NQOkHTaAPN6tAsqqle8LxhUHErmphu
d5qn4famnJQ99UUrugHR/vic3Ywm2myaE6Lq10zh9MAHrfAnvlShmdybUJe2MCmv2JOpnrcK
zb9Ad5AVc2xlgPeyPeFSNTkoMsCbGV/kwZJ8L6Cb2Z5ICYeFJNs70HvZHoofwEnOPMB767jW
SoMkmxjgJVzvXHVQhlGF3LERaH4Gd3Sex9Sd2+e+87bkDEY9db57TEYT9slokUHlaprtp1jj
uWx6zvbmolE/TmvrWK07sWi5rJ5OnsE32J4Mw4qbe+Nsj2sHbFVQs3XcJWwP+Hwwfi4aJ27s
L0eyGPMPipSleyu6Nc+9UT6nNwfCX7H2/gwnmw2Ht8z036Z7PyA62Hry6BrgvRQPuRAmj/8B
3kvxmOPVnDxeDvDWXRaJV02y9WeA9+4yUMlKzx7YrZ+PKQb1ksXvAV5Rtz1Vt/ODd9hVyB0L
gRijblGvad06JDWA1hQ6n33yZ+fuVDBOCJAhJi45bcftS5Zk885nCuZiqaU3J98ETofa00Im
lZvsK+ZXKp0J2309Zh93dwaltSadxGrWxMgXLclN4sVNYioaKE5Vw7OxNW4hxJyt2q6xEbm4
SkyG0yF0aEDAPKpkw0xo0b0J3t8neD+lOig9udEDvJcBkBVskKQAB3gzz+sFqmZ53gu8l+cx
FU56RRzYvd9gs2JJM9cDu5flgRTOTvMN8AqW1y7SK8OiQu7ZhyhrZ2aKnrbsLF3RJQMZV8fv
VDRYqvQeR2+DEMtNkokVXcZRWz0/faeiqcUqGLBgZ83KcMaiby0Nfj1pH3f3xhlE01YbA7Zk
WjIWLUnk/fFJuxmNX307PE0JFfyGlGZGtGSK/GJOeTacFn0OZNactHJWkqZNHVtvnvejsoNa
ICmhdGA3p/H8tFTOuoe8wJvpHYXDebIUeoD30jsSP6GTOioDvD2N13oyTTbAeylebSVaWHI/
lAO8guLhRYZl2FTIHesAckbQBKBxGFMnK2i0xOfqOpM3FU2k5XqVyn4ncXaUllBcsTdPrbaz
c3cqmsjlOY2g8NFtNetXs8Qx6ZriDZOKm3uDvjPVN4gaKqRzeUso3tVlYiqayOU1QkU1snAG
/jW5vMlwWkx2+3VPjMCSo0sw6ab95ni/Q3awUjJTNsB7aQBDseyo6ABvbsvzO5uk521f4M25
PC6KyTmMAd6czdMiLZvNe2I3Z/N821py1naAvzubN5wq5I59gN81arjY+wFMnAyIJoVl/9KV
d8H0poLB4r/4LlF3UtHkdGosWhBNv3B2mIumhrBdt9ZB1ABzv4a6ZgbjkukNn4qbe4PVoFqN
cmd61n8R04M/Pmk3o4lftCLGgCr3p+jRL8nlTUbT/L6n7ExcNWQu/9Oag/QdmoPJ2t6Kqt4/
V92PSjfLqvu9wHvJZw3Fq+Ro3wu7nXqyJbN4A7x1j1uvUXpNqrgd4K3foUoo3ebegAd26+dr
LcYIkspxA7zgpUKnwr3OCIaDhtxxNZDinBO7OXlnv2Xkcj+xaAX3PJWreExGw4UqUeuMXXpW
sioWrSgk27l57OzeOL0Jn+JGIVWY3JoVI2YXSiJfD9rHvWCwMMWoju8NhJZINgG8hHqeTlA8
pqMBrmLUBYSTehmx5lu35nN+a9DvndZCeVGSnkCzfba/nXj+t2T9kvmnA7uX5wmVmnxPHNjN
PE9C9DjL817grTvsN+NaJDt7d4D3pvBUS5Z0HNi9ewwWA0dJoveFXlJPPneckOGfIXc8DayE
yJoRohi35HNra+rJrOeCfnPRxGBEZEm6VfM/2QZIWKB6jHbqO/M5GY2WDsjQpBI0S9aTdbLG
979ZxlNy9PWkfdyLxq87EK6n4tcVs2QiCyenD/6XHenF7O9UNFCModYeIlPwopKpvNyKWoO/
BS5aFyY3x4Bb735JUt/6bArY3uXkRWRvv6JfzUpXvLCbS8lSumSVug7wdp4HkrwUvbB7WV54
W6hmOcpAb/0OpfeSbU8+sHv3GEFKs6xR4UCv4Hl2kdEbfhByz6tDGnbkBuxncHJsPRat6BuE
cweFuWioNO2Veo8uyOx7whet0HhpeMHzpqIxv0VXNKUnOYJcNdnW1F8Rz1rTvp60j3vRPG2x
q2KohErWK2iJJGulq7bBqWD8rSiNrHY1iqxrkuWtEVts52bFs1tTkcT8jmTNn7VsgrK+U3qr
WN5PCfppVpV2gDcn9VrR7Dk7wHupgEYDcbI4OsC7CR+F+kJyUHmgNyf2/GXSk20EA7yZ8hEW
yHaIHuAVqTA4e9f7MTzcIOSORn8rhECRdzTxkysr6kcrZFK4nRU9H5PRVOdu4uTIORIZJLv3
fdEK+tqvmrqmojG/DgIphZ+0WdKT0pYY5znhu7haDDeIW9FgmFs0UPWfQ4iFZhnfGnO2M/r6
mIwGil9XtDcn4039IpZkfLLEOO+K8U3uTaUq5K9RRalJydxY9GZ8f3tMZL+mn/asisUB3svy
MJSOs5J+T+zes5+pVMas0ssLvHePkQvUpDT3AG/9Dgm1RKtyUrb5Bd77CTsXkWST+wCvSOmd
sgg/d4cRhNwztWgdyKhZJWmYK6jFohUpvX5RUJuMpkI3ZIHeEZMJyjqZm7ij9jIZjQmH1rHT
IsO05cgKy/GLIYSvJ+3jXjTg7Nvvs0AgDCbJCxwsybfWyhcUbzIc9V1prfvPR7El5SnCEf5b
d+dzfneceMcYsG8SP5/l//CIyH9G1y9L9V7YzeVb9qcraX8zwJu5XnPqkUyAv7Bbd1iIng0m
SdGXF3hzztb8/Z4UzhngzdnGVjCb+RrgFUzvYhJYhwmE3lHmpxKKug26H8KSLOnHmgXB6KmC
zWMyGCxG6vc7DwY6pl2llgxpt3o+CTy7NaF8SM7AVf1NliPhsWhFKu9UVuTrQfu4uzeIoMzs
P1YPKNujhyt69Ohi7mcuGj/4SNXvwMBO8S15p4i5sRWbA+d3itlwuj27QUMsCVuyuxUmnW3e
PO9Hdf2ilSht0PEC7z3+KxaArNjLAd5M8WppnFUzOMCb03l+SFPyPB/gzek8KVqThfkB3pzO
kwLJnO2B/eZkng4fCL3nA9G6ADozIqSsoG5d0ut/mcybjaZCl45BWBsnZ402JPNmozEVqj0k
A7FLNhr73nTR15P2cS8aiN5JcJan2nx3koOdq5J5ct6hNxuO89SqTreotgr5ZN6agejzZN70
7hCAhQ1bq35NeifzdpK8nxL2k1az2bwXeHM6T4tIcjZwgDdzvR7FsCzXe4E3J/TMuUdysGqA
N++yFW0tK9/4Am9O6InzCsm2D77AK9jeKT/yM3iYQeg9ow7/EZuAGDH2tLbfkmieUoJnR/BU
NFhU/GfP1UCwJusSuMZ2pJ9ORH9O7w0CKVNTI4SWVdjGFQ1glxm94QVxc29iLgk8JMHWs93B
izJ6p9o3j8looPgDhp2cG0Hz23A6o7cinMuM3mQ4XbF7MMSNa5bqzd2wfzvV+xZpP0zSKlzB
qP654n5hTps8+Ad4c+fgk20kOwef2O3003/G2XLyC7yXfiqVmuQZB3brN6g9pjM5qcR5gPd+
QvBbQ4OkBOYBXkE+LyxEdNhU6E0LEYk8Fvih0yzZTeqLVgw2cz+bPnhMRsNhutysCjRkSk6G
+KIVAjbPbuYzRjAZDah06N33ptek550vWpNqvCCfw6XiVjThN1E5xHiEuj9w3+tSkebSj8lw
ghajeTzdf0CWHm1ewqUvyefs5pihVcKG/h/Icum5Tq3fTj//UwJ/0JJcZYD3sj2iMFLKegK/
wHv5Xgi6tKwn8AHeustNsVjWyHKA9/KpEO7DpH7tAG/9hM6OCiQztgd2Bd+7sHfQYVahdywE
JPLxzfzUqtEPlRQMXqGbiXI61vyYDIZjJhyqB9MrZyWsuNAShb+L8czZrWFtYYpCQsiS9PAu
vIbunTlvfD1oH/eiwUJqRk4nmDlt5kdLgrnQcp4NBpzjscQQMGWZuC9aU1Y+25rP+a1h6c1f
U74xnOR6vmgqRf/mer9C349ypYsDu53itayn1QBvpnhcNKnMcGC37rB1KuH/mJOOOMBbv0GT
VrglSzQDvPcT1mATyQ7RAV7AI54aGWcn7/CE0HueEM4hGJ1vNQDQrF/HCgU5VL6o8k1FwyXm
mp20oqr/tpL1/jW9kP1Uq/BzOhptVbvvDDl1TQ4hxKLv7h4crhC3ook+QIhOaRKVisnW4EXd
g+fhPObDCUWhWiXS9U/rmW9st/tLOH981m6HY5E59phQ1GrSgiRWvXneIp73Uwp/3JKsfoD3
Er4w08026A3wXsKn/quG5LToAG/d5afAMGtWoGagN2f1pBjm+MeB3bvLEJPIlCzjfqFX5PXq
xVE87CH0nj1EMxanFc6WkDCXb9E1Ishy6kDwmIyGnY327t94ZavJTJivWTHNY/2sUvg5vTVi
jSzk/dIWtLqkvfNCQ+7rOfu4FwyWGKtoMZegiMmJhFi0IJp6lUCeigbC8EY6MNVKKJYV+Fvh
eON/47kb4Ozm+G+xG4WDD0BWqn5y/vxN+H5Y4E8wSaEGeHObXnQHJPu/B3hzo144RKXnRF7g
rbtcO4TbSvI7PMBbv0OKRJgmLQIHeO9z2K2gJkWcB3hFc9tpj44fvcMZQu8I9tcCtbdeu5j2
ZCna16xJ6120T00GU6M8SEDEUpOpa1+0gq/2q4ra7NZYq6AmrYbCbnZvVnC8epVAHs4Qt6KB
4tROO3G4JNe8togu6W27EHGeDqcRKTc1BZbkqwDWJF2p/vFZux9O1ep3rnCaI01eKGCyyfXN
8n6Hwl+rScvHAd57yFYrDFll0wO8mew1PwrTZO8F3rvLIKXW7Oj3Ad5M9qS01pMDqgd47yds
UoRzx++BXcAnkC+69IYnhN5zuPBLPJPTI5Nqye6pukYWT09zk4/paCqggKJ1ZE6avdYlOaMY
Dz0/fyejCRZRnR4pUEv2gsWi7y7hDk+IW9H4YcH+hPmuV7Gq+RLuElk8OSNHj+lwNLyen216
ULOCX4u43mUJd3Z3AJuwmEg066Ur0m8r3r/P9far/HXJdoQc4M0ZvVqQkiOCA7w9oydpzYkD
vDej13rpmFQtGeD9Gb20JcYB3p7R0yyLeGFXkLzTi7wfvcMWQu/ZQgBxyEw3acZZRaVVCb2L
ku1kNKFhw1axY+vJrkNftKKcbu0iyTK7N60xgF+kVTHpwuuLFlwnatWLou0whbgVjfObUNd2
mte5sybzk8sSeueGz9PhNI/Gf9e+M8x5I95vT+jNhlOFGnUNFy6sWQ3Gd0JvBcn7MZU/y51g
B3bvCRtDFpZsIRzgzUyvF+rJqbIXdu8OE99Qcz7Ae3keWqGaHP0e4K2f0LlR3Oazitgv8Irm
vIskiw1fCLsj1h/SzE2sQzAKSIrs+qIVCsjSz50UZqPByk5dnVsztmxlvay4C17qOc9GY+J/
evVgpCW5RF0igHMpsmLDFuJWNFBabxq8FYkpO3e7SGQFLiT+ZsNRUWeQ/nZ0oodJJfQNes7T
uyNIVYBCzdmS7six6t/I9Oo/XuTv1kRBcpZgwUtyAS/+KenB2pKZpwHeXOYGPy2y2oMHeO9j
JjGnn+zHG+DNGVDFsNxMXi4Gei83pl64Z73VDvDWT9gpVOuS89QDvKSr8SyZ44xl+GnYHY8D
bE4+DMUaWOfsQEFbQ471tHL/mAynlsoEjYxFsaa7NFeUcpwcn4+uzEWjxVkKdtNWzSx5tPqi
JX2Np1T/61H7uBeN37Ib+U3MvyfLOuPyokEcO0+CzgUTznTUKgAp+NsneZFf5GcHdOZq+TkZ
Dvo71JAobGi4p40g5V3oXsX1fkp/MHT10/qDAd5L+ZhD+ynJVg7wZsqnRZL2ygd2L+HzV22h
rN70F3ov4YNaQs01R/gO8NZPqAIFKFcyOLArUqGnk71+Bg9DDbtlQWFORan66c4hGZJrXn8u
WkH35HyAdDKc0p3kCYuzvkpJx19ftERw+jTd9jkZDRcU6Krop7BAsj61xr64nlaJv560j7vB
UIPWG8bcsCSvSrFoRZHY/vig3YwGClsnZN8d/9nUZFXEVy1hr6eCip+T4aC/oLC2ruwxIWZ/
N3O9L2+69xskCIGTd5QB3szzamHONuYd4M08j4o+RxdTRO8F3sv0ulqxlnw3faH3Mj2Rglkf
rxd2b2Kv9jDpSib2DvCSxN65s4gN9wq7ZZDQC0E3DgtjTU9e+aIlVW88nyKdC6eWp6gGg9Mu
TgqF1DXBdD6Xmp4LRkuMsAA7I9Ym6bwerGF6f3zSPu5FQ6XGgASKxXy85siEL1pSJObzaam5
aMApaG9Owqk1vyQle09DJG1JYu/swvc5GQ6GeWmr/pAZkGWPrzI3fPlmer9IhLBmyx8DvJfw
CZdKlMxKHeDNhK+XRsl6+ABvJnwAeQmdL/RewsdWoCfPhBd26+ezGla+uc93YJfQvYvOs+Fe
YbdMBVrBKIP7tb5rTfY4xqIVxr9yavz7mAynFrSQze0qANSzLZu4Qp+m1YvE3lQ0XCT8mJ1U
+P5o8voTTclL+N4fH7WPe9FQiSF1C1Fj5aToRKxZkti7uFdMBePEzRojawhOx+5k6d53TyzP
hmOtNevRdwy1YjZP+Rad/vt87wc0CA2z/fkHeC/HQy6U7CU4sHsZXtSLe3Lyc4C37jGCkL+g
kpXRL/TeXYYna0tmHQ/w1k/or/cCknwQB3hF+faK5Q3/CrvjKWDRgVGdQnRFzSrt2KKcnlyk
WqaiwcJk2MKS1qRBshhdVphNo11NF0xFU0ukJsk0bF8gm4VfY8aBF4LmNtwrbkbj5KH7I1Y9
pCcjzjVSLrhdVrgQNJ+LBvxJ08qhS8NNOdn3AEsetetBlslw/Efjr9Kmxl0wOco6a/zyZnm/
Q4PQb8NJsneA99IAslLzQ8sv8Ga61517pDUIX+DNdK9iaZqcfPhC7/0WOxfWdD3xBd6bcsRW
NKnVdWCX9OpdHMHDuMJueooIA4GGqktL5lB1clrxL616F2PLU9FgIWDCyrV27slWSlxjFtxO
nSs+J6MJdS1nrTGe0VTScjsrLFIqnkbz9aR93I4mTNdCSsrvFi09Ur4iFd77uQjhXDRO24A9
FNZeqWKe7C0xSTm9JX1Oh6NK4SQJTvpCWPFbh7DfZO/HRQiTJccB3pzSC8fzpJfhAG9meVSM
konvAd7M8pQKJMUUBnjzLrfniZDc5Rd4b0qvShFIJh0HeAXLO5W687N3eFfYHT8BK9SVqKFf
2KQnNZVsyWGFYheJlqlosIhzotYBuhAktdR80RJxmqs8y1Q0tXQFBietRpWSZo+xaElK76JP
bzhX3IymEoXbmlVqz5mCXEpvib0uXtwnpqJxviatdlC/eVXJ3pl91fcqB31Oh+M3PP/5azNS
keT9KFa9Wd7fZ3k/pUJonByDf2H3kgCG0p9zYamRjBd4c4deZOizExlP7Gaix1oUkofgAd5M
9LAwZrWPD/DeZF6IM1oymffCLunPuxi8HbYVdsdKQP2uphLKzNVP32TCSJdQCRQ8k4t4TEaD
4SAUCRYPyulr8ipTVrzB0PCiPW8qmihbUnN+1zweyLbTrql1Yj3bm68n7eNuNKgkyg3Av6vk
haKu6c+7rNxORROVWwOW8IPqgrS1cotXcpeT4WgPh0sBJ69MyYJerPo30jz6DgnCpLTZCk2z
f7LUHyUHtQ7sXlpS9akekBT6e4H3U890ofYAb93jSuB8Mj1SPdBbv0UnQyWajJKyKi/w1k/Y
yYpmPfcGeMGLxbfjnBYMSw27Y3OAUqh2qw1Fq2azz75oRZFP+kXv4FQ4/lKiDsad/Q9QVk1u
xQwZml7Ir01Fo6USWtMqRgJJ/VBdk5pDuehSHY4at6IJ7YPgNooIT+vq1IDIHMVJS6U8JoMJ
MQzR3kKevEoyX4NrZrUvdf4moxHARk6pm/PQtPDLW+dvGdH7KZ2/cABN6/wFeC/jEyq1ZWdF
DvBmxidFRbLSzi/w1l0maFo4WaUa4L1VW4NSs8JmL+zePcYawxJZB8OBXpJwPOd7bRhrtDtm
B9hLq42bcyNUTRpbxqIl882nDOkxGQ4VqGDO+Ay5Zh3haFLH4i8CMOdpoLlorFSu5ISvGYEl
VbdtiUy1X5fPc9tt+Grciob9Xmatd/B9saxDKS8yPTlN0T0mo4FirOEO0tWc76WHK2wJ42t/
fNRuhoMxEdyVwSlspaTBDr4Hgpcxvt1Sf1B6VudngDfXlcX/0qQY4QBvp3qQbiE8wHupHlYs
NUv1DvDe1B6wv0OS9Y0B3rvL0Z7aKEv2BnoJ2TsfFWnDKKLdsr3wKxtVIw6lXcJkzQ/WdPDL
qSnJYzIccm6ASFGTdWaRrf4vIRTYTjfnczIaK37ycu9+BEePZ5LrrfCLca53ca0YRhE3t4ar
VurAtVZI2oD7oiVSNhcT6HPRPGcroiMS/VlLdhIts7c7NzKeCwYLOb8T9ete42wSGScT/G+m
94uk/lSSWfYB3pzba8Uo+TwO8F4qoFDIX2i5X8wB3kv4/H1RGLOeaAO9N7unvWR9Rg7sZsIH
Ie2SVMX8Qi8hfOdTI21YRbRbAv79eS2ihs3Ekq0csWgJf23nRrNz4dRoHjYgQOphS5AdtFgy
gMrnImxz0VgR6ASdlZ1WJPt/fdGC7khnfBd3i+EVcSsaf5OEaVvMOgtrUrrd1ywIhi7mk+aC
Af+WnetxjKFLzwpLwpq9AbmgfFPhOHvziylI7Q1qTxen5/Sgfh3l+38AAAD//+x9S5Ikt5Lk
iRoC+wJ2gVxEHqN7FrPofoue+8uYRThy8SjuZQ4ikUUyKM1iL9RfhYZ7OBQGM9V/mttfz/Ym
D/BemRfLCyYPmgZ4rwBgKmhJZ64B3nqXO7v6hWTVbIC3focEUpolWwkGeK8MBSotaVh2YJc0
7F2cqo2QiH7HuV/iB9LU/9DKknRKj4sWsNFTM5vHJBuMw/znaKOvvJyMA4uLVvTrXQwGz7Lp
vYEI9trxhtffkha30yPCryft4x6bOCJsQtV3jFVaUhPNHhHeqelNsYn6nEB0C4SzZDq/Q1f4
MF5Z/c2y8QeNFAnAF6OsSebb6u8vbvUnyfPRAd58ghvNG9nxjAO8Wen1ojXZ4/7Cbr3HANAL
tqSX0xd6e9mWenb++wDvVXqdi0jyFHyAV2g9Pmsy9xV4BET0O7b9rQiyhTmHqIvm3G+/rbFN
0dN52sckG5cG/ixYB2MxyPZRlBXlYOh0bvU3xyaSykIWQSURSv4eVsWbnZrjfT1pH/fYYLjs
S7ghg7NKnkbjkikgJLro1ZtiU4tQE1V7pia3pN+QX7XGh/GiV2+KDhRfKP2e++bCJWy2Z7fU
dznvz2u9H3D6S97gA7t38cfIAEzOPQ7wZonn+2lNTowM8N5inlAx4tyCMcCbi3lWenKncWA3
l/LChDtp8vfCLpAQyBeL7oiG6Hf8+qOHtUV+rWqD7Colaw5rVS6686bYhCWcyzpllSbZUQxc
MrxwXcqbZGNE0siocTT9bzx6vi7ljWSIW2yiKscYRkMAhsnOyUWlPDrNSX5MsomqHAL5H60B
9mRQ8o5a3iSdHr6LPXwLtdU0nbk+nre++z08/iBbQxngzbU89d1Qdhjjid0s81x2WLZJ/wDv
r+VxyyrRgd5cy9OilqwrDfDmWh6WbGvegV0h9eq5yW4fwRD9jlt/K6wQ44OGVilJqC1xpQU9
PYN+TLJxZRByGKG3xpJMUoiLVvTlnVoGf06yoYJgbFIhDIOTHoy0KNPsqpI3ciFuscFCwC5A
ujGEgs1W8lZ0sj3LoNdP2k02UcmL2+JbpHAoSdoW1jUZyZeVvEk6Zv6bqb5k+r3RbM9RqX9L
o5Vv8fmDpH523IK30bIhkR9w+sNkos8Ab24bbNHFljxmPMB7JajUUrNWnQO8V4JSlSLpULaB
3votuqLMn3gP8N5PCFYgm7U8wCuOk6+kwcit6HfCBHppFTgivTpRtZw0iIsWsGG7EKFTbLj4
GmooQJG1lqw3xkUrjpPbudn0LBvAMBYhFwUMyX4uXjKpjYAXjQsjtuIWGyzVdTpz5W6QnAaO
a1aQOc3geEySgQJASgxMVVt2swMrBPWlAp0iEwoUGluXKDPX5BRSXPV3VKD/LKu/rHXyAO8V
fMQl4gyTvsQv8GbBJ/6rzm4vDvDWuxx5sKVmB0W+0HvllPYiybPOA7v181mtBSk5iTDAKwRS
vViER35Fv5XGwfEEcmTIccWsRSUvWbl8v3Nx6jdFxzeh1Qy7/+5bp2QPCi8pbEE/zT3+nGQj
pVdqqpWIjZL56HHREr13sbMY+RW32FDh5hKpNeQwl8x6O/OSA9kLb+c5NlAiVZdd8jXpLq+y
Rbo1/i+/fNJus/F7Ir6bbFRrVozDpDXPW/D9vNMfxIBq1vjlBd6s9Kj0bFbwC7tZ53HRlvUD
OcB7C3stCp6UrN9+obd+i01rWIwmTzoP8N5PKHHAmvuhHNgVOg/OhJEvviMlot8y74cCVcC1
RKTJWPIFv6ZCAcoXYyJTdLgYdLaq4r+rZ9RWzjZ4SVZwv2jummTTTc2sRdmVk5vHVSbI7ULn
jZyIe49acRJGLQx5WrIpEiYb1dJ9d49JMrWEuR/Xxi71pCbjLusSK/TrNsJpOtHdaa1j42SP
5yybt877jXz+mJOdegO8ucms+g4kOzNygPcKPn0afiYLJAd4b2GvR6ZENq7hC725sGdFLOmW
OsB77zP4bsK39MkBuoFe0VB4cZZrIyrCbvn3N//+esUGHVEh+ey2oisOc+Uiz3WODhfQpj3s
b305Tue2wYICEtjFUjzHppXq4hUR/WVr2UmltqaAhPrLR+3jHhsqtUNrFkYj2iin+uKiFWwu
TnPn2PhG03+N3NT3S1Ux6QbhVy05aT+N3P6cpAMFSVrrYkoEaUk+tza8Vd8PW/2pJetmA7y5
Z68Wyx6dDfBeBcBhKZvt2TvAW++y+BoNnLzLA7z1OyRkfxkmj3he2L2fr0LR7G5+gFdovH4e
qmAjIcLuhSoo9NjR91ZZW3bhXTEqBs+A1rOFd4oNFgxbSmR/L2UXqrhmhcI7LVJ+TpOBSDVD
cxWB2U0PrmkKq6c+218P2sc9NuBizRiFBKtIejx4Tb+e/vJBu8nG9+eda9f6jLNtSaOhuGpJ
x97Z1uhzng4JxVB9q0o1aWHqV70l3gKJ92NWf5Zs1hvgvUoPW+Ga7FoZ4M1Kr0cXR7LUc4C3
3uUOYYefjMUc4O1KL6ujntCtn46rS51kF9gTukLjnSav+9I7QiHsjlW/+G2NaLbeRTVrZSFL
chRA8Hxcc46NKxzDJtS0V9Hk4X9ctOLs9jTy9XOaTUNX4ByjZdWy8XmLKkWnJdavJ+3jHhvf
6BgSNf8HQZLmE3HRijIeXxSMp9iEm4uwa++O/p9kNMwijXd1djvLppO5WoWu0XVI2amMufLJ
W+P9tMUfJCe/B3hzGQ99P5jMCh7g7WU8qcnUswHeXMazkl/OD/Bmcdd83ZWkb+0B3lzIc52T
9XEe4O8u5I1cCLvj1h/qMzz+lBmoZVNSii6YfAE9bfZ/TLLBgiamHLEDKkmDIyy04uTZTsuS
n9NsgCk8ygnNavL3EBd9dyVv5ELcYhNFOf+hGkjcmqSH57JK3vnIzxyb0GtNKol1gspJa566
RrPS1VntLB2GDsKipKppW+p3JW+FyvuZSh4XSBahDuxeqUcRj56sogzwZqlnhXo2suOJ3VvF
MysVk2cMA7xZ6EERySYEP7F763jUS9NkyvIAr5B5F37ONiIh7I5Pv5YKzWL99acQk/Uiv2hJ
lvBph+Fjko1rHPHvqPVaqWryAYqLVtTyriosk2xibIG5m8YZXTpKeInMu5jDsJEIcYsNlC6t
dq4xZy3ZU46ywqf9Mpptjk00VLOvLr6HQ6eUL+atGbi92FFM0vFV0rcUDatW4WyDof0l4zr2
abj//tf//Ov//et//u9//gdU/+c//uv//O9/bl2okmv8XnmUHVpY8FJeoMJ/xOuQI/YwuRi/
sJvP0p8NK8kV6QDvfcgEwg8oucoc4M1F9XD4ThZvBnjrdyiqYa6YLAgf4L13mdgVAieDab7Q
C14s0M+tb2ykd9idSAUq0Ng3M0JWSZLtebRmnETkogw2ySYySHokzSlpcjMcs0sL2PTTGMDP
STbd37DSOsTEuv+ba2fra4aIn9ry+kn7uMem+r2JQnivho05W9JbcW8uR6Jn2XTfVETfZCVE
Tg5tzkaRpG0oPyfphKUkRXqP3/fKSZ/6WR/Kn1biv1e99Se9DllLTxv2HuC9ko+pmEqy7HqA
N0s+LVyTViIv7ObCOrmGS6dhv8B7BV/z22bJofIB3nuPsfu7DpMdnl/oJSfs5wFnNjI87F6G
h7/pDYEbVuOkyRktOfd0kXnR3DbJ5pldG41tvaVHmZbkm732eWer8BSbXnz5NaZmqNSTp569
4AoLHNSLrcWI8LjF5in4qlAlIFex6UPcJYqPTn0oH9N0em+E5vqVMErKWcW3xqv7QvFN0YFi
0URpvrEQxuR2GyYjNd+K78fNDlHCfS/pfnOAN0s9LJI90hjgzVKPIgQ5a3f4Au9tpiQtJkm5
PMBbv0NVLeEmkfS+eYE391EAF7Rk0MoXeoXYq2dVCl+CR1aG3ckwoMIu51mhWpVnD13ObXiF
2NNTf97HJJtnuFJksrgq7pLtgyi0JMfktGXvc5KNudgD41ZfjRDJN/OSCSB0/fKrJ+3jHpta
pPtPVYE7SBPMVZDiqhXqqF6MZ03SaXFvIvcDrGXPS8IxZ0W18qq8N0UHit+RzgT+j3TJKXGY
zAZ8i73fxfGQMJJyc8/uAO/VfOKLp2YHaA7wZs1nLuOy7eEHeK/mYyrakybcA7xX80GPuOGk
5jvAm090RQomO/cGeIniu+h3G2kZdjNfotYu0b/HVJMZXHHRivLe1TI8yaarUevWGvfsAE34
4C8p711MNUyxidzyRsj+PTXXFskuqbLC+9MV30UheaRl3GIT2o1q9IhGQTnblrNI8V22Vk7S
0WhFNMauWhukR05WtFYCXHjhTNGBwkJcXfFxOB5mZ9h5qvb6Vnw/6XZoUFr23TjAe1UeRLhU
sl1qgDfXfPwv5aTDzABvvctxpigtqUMHeO9d7r30mnUvP8DbD5p7dtRzgFeoPLlQeSMrw+6l
S5i0BqjWGDg5U+UXrWDzdAU/W3qn2GAkVHZf33yhUum5lTcuWsCmnY6wf06yoWJNpAJUJky6
V9DkudofRN6ZAP960D7ukXG51iLzo7nI03ReZly14gy3nd2bxzydCHdTNDNRSTsEyoqia+1n
d+dzkg4UUI3KfiQANcoG1s01775F3m/gd2itoGnSEucA71UB5H8ppOekX+DNWs8KJg0SDuxm
paelU7Ipc4D33mPD+EuTVdsDvFfpiRaoueLXgV2gJcBOTUp6PeIx4v+5pfMwmv85PIclr/OW
+FrLaV7dPBuFrgJk4dadTWBYolo7ns5JT7Kh0lBcGimwAOScoGmN5SG2Xz5oH/fIhGLTZgSu
9sAwWS9aVMwjOp3In6fTu28nXHMxMieLI4t0Hp7mk39O0okEyo4SQYKinHzW/KKp18Bb5/2k
56FRgayT2wBvLuZJEcy6fx3g7cU8yBrNDPBmifeMoEwKqAO8v5iX9cIZ4M3FvEhCS7YODPCK
Yt65RUmvMITEvUwJ4y4NXecp1vQu3lYMrT6rbWdL7xSbqMv5mttaOB8CpycJv7mYN8kmCnPU
WzcgoZrskl9WzTsrtH49aR/32LjAUWONiAwFSA6tLSrm4Xkxb56N/2yIBdFqy9YcVok8Op32
nqQTxTz2e25VkSXZqxsXvUXenxd5P1HMk+rPImWPow7wXhXAtTRLqtEB3tyeFx6myea3Ad5e
ziNMNvsM8OZyngtM5ORdPsCby3lSOiefwwFeUdBrpzORveLQE/eiJSwsuRCQmATTJbAV6kjP
7Vbm2aDrI2ok1f/ns3UJWzKQcdo6+TnJJjpj/cFRMqmcDu9dk/rRTjNMBpmPe2RCtWFliLAM
F0fJX/cyrffLJ+0+nQ7VhR4i1E412523Zrzk3Phwkk4U9Cp3dZnXBbLxDJOhiL+71qO01rvT
c541NVnwKlo2JbLb7s+fKE4mbwzwXmWCWjj77hrg7fqTIT0S/ALvrSjXOHRK1hoHeOt3qNgL
ZgMIB3jvXa4o8b3k7vIBXtI4eDqm2SsNjXMvw0ND4hiSYrjuJqtzK5pIQE6D2h6TbLhAcy7M
rWOtkqs1+kUr2DQ7bdmfZKOlg0X6TQNrLfte9t3YColzPno+2HzcY+NbbXTt6buCFgPOyZnT
iPBdQud09nyajjkNV9Lo+x3KtmDVNZVguCo2TtGBImad/SHu1nuyDzIC4P+OAvQf5ffXsoNn
A7xX8QkV4qSeGuDNik+epyhJxfcC71V8vZeadXQa4L31PK6lQvI7HOC9d5n6MzkiOxF8oFfU
HM8tnnvloSvupCxQAVKzRq2rQs+OBC+poMqplcVjmg37IsxMzKYtm9bjF62oOZ5bPE+yCbdm
fJa2oLmWzf0iVlk8y0XRkYequJfn0YT99yoVCNtzHPy38HieptOJjbRpZA33ZMNqXLVEwp4a
Dk3SwXgPCFLFpqLZqsrke+Ct+X7e8e+ZspW7zQO8+Xg5/tLsTOsB3i72Kia9uQZ4bxMBydPI
M+n49wJvLu+hq/TkdzjAu4u4tWC2RvqFXiH27KLAJ0NQ3EvAYHGlp7W5qM8OJaxIyYkEkfP1
d4oL+w+eWa1rx4qcYxMXLWBjfFHem2JjJWY0wVfgqqhJgzxbUnq9HhiRISbu5V/4dqdXitTs
1izZtbpqYIQvzpcn6WiUw7ULQZyWZ5XrCiPx6/LeFB0oirVaRXNZbMktX1z0lnqLpN5P+f0p
t7zfX4A3l/d6UcgmuB3gvVpAfXHXbLTXAd6r+FjCOiVZO3ti9+q92gsmcyUO7H6115NHnwO8
4jD33OvP/4KhKO6FX3AV10bqosKX4LTX3wp9JHgxsznJppmE8xM1UkmeF5LfnCVq72JwZIqN
FVJX4uzb1tak5rRrXLRE7Z1mtw02H/fYPEctEEU6CHdLd9+t6I2kUyX+mGbjIhya1d5Usvcm
LvpurTfFJk5lDboxoDZK3hu/6G/ZS/i3d/rrljwkGOC9+g6sGGCytHyA967+TP6STfbdv7Bb
7zFyKz07AD7AW79Bqn7bLHmPB3jrJ+SI2dNk5XuAF6iIpzPD2brbhoq459vfMBYpJWyUTOaG
JR4jLnwv7F+myGAB9d+8KXW1bEEYJwcc/2D/cuq9NsmGCnQnwtWlMFFyw0hLeg8RTuecvx60
j3tsXKvVuC1QXUK0rMVIXPWtzYePaTpK4VYowrUya1rirTi5rVfjIpN0DJvfFm1Qu2VNJevk
oNVb4/0eRn9KySCvAd58eMulU3LydoA3S71etGcPbw/wXrHXrXBPJkkO8N673LlkzRyf0L19
hP6VNE52Og7wilLelQdMH2rinl2/xUEnsUuJ8Kbd6gHDZ+vVY56N752aS4qKmrSKimsWkLm0
gJkiE5niShoT2w2eMRo5C5jvHaT9etA+7rF5DtI2VxO1KdbkWdGq0I7TKefHPJsWMi/OoQF8
Hdw55Xzh5zxJB3x7ILVHXKN/WS25ck1GAr5l3o/6/GHp2TmHAd678qM/WJWTviUHeLO+868l
Ozv/wm4v5Ul2+RvgHyjlJWfZBnh7Kc9fhMnfyQFeUso7TVLo1YaMuOfV3wilIyiiYFrhLanl
6Wkv+WOSTZTlzJcq61rFkkdoOJk8cKeWN8WGfAnVxmiVhDC5H6OCS4pfdjHvY0NF3Ay5qEgI
ET8SRbDs2MKaWt7piMxjmo761tdcSbErPYasxvv+Wt4kHcPoZyXn1NLprO9a3l/b5683Sk47
HuDNtTwt2rNTtwd4d9NWGPjmfVYCvL2W52ti1ufvBd5cy+uFBbIRci/w3nqeQUn6wLygC9TE
VWgHjGAIuBvaIa2GJ57/N23nvOTQ9pTM40+Qqf5/rbKRZRsn1iSQtNPq1+ckG/KvWawzgd8Y
SGa8+kULHrTLGQwYsRC32EQdq5HzgF4rbS7m0XkC75+gI91cEvlXBbR3pOSqmDdHJ4p5tUJv
rsPFkvM+MNkg8LvrvG/x+IOkRxKssK3767r83fBw1p/wcEZopWny7TXAmyuNViyZS3pgt95j
wupiLVu3OMBbv0F1was12c8wwHs/IfWClmwaHOAllcYLWTAyK+BeAgeQakUzir7Bb7V5+Hcy
p6Z4j0kyXMRaRwNQDMeX5AzwnFHZHyz+zoO8ZtmgSGM4/k2WtcuKvPY4UPzVg/Zxj02UDGv1
28OtiQClx0JWFBprv9jqTNHxDWVT33RoU2HIvu7Lio6SC8PCz+mbY6ZQYy6stQ6WNWefC+L5
3fXnP8jir/k7JtkSNcB75R5x3lNlgDcXG59GLlk7kBd4r+CzXnoy++zA7hVTLoJb8qTmwG79
fC7QS3KC5QVdUWiU86Z9GIEVcCdFACPjoWEFIfVlK7dg4ZLmJ5ALh905Nlx8karI1uKf5Kkl
TzY//aFr8GL5nWKjhUQIDRmsQfLwRxfN/8p58wKMvIpbbGpRiGzC+KKg553wVvRiXJo5z9EJ
lUNhuqgm6HrvW6XRv+vW08H5z2k2gggW74FONZtsX+Z6jd5C73fw9SNNFvQGeLPCo9Jb8iBv
gDcrPC6anWEd4L0Kr7vwrcnRiwHe+h02122191wNY4C3fkJ/rApA8sB7gBeoCTr1ePD1d0RD
wL3YDu4Y85nRPyi51TeuWdE7KOfTIXNkOJqZOSypoXZNBp3GRSt6By/6uebYiIscbj0O/Ju0
ZJlF1iijerWlGLkQt9hEQBELgesi9Ucu6c1al3gKub48062PaTrdHzFiY8EOmjzw96vW0Pnl
s3abjlGM/7bm/wFMGgLUyf6Ft9T7jXz9WrId4sDu1XtSC6UzO57YvWpPa2ktecA8wFvvMPdW
ajIN9sBurudRiKNsE8ELvPceo983oOQsyxd6SV3vfEYTRigE3Iu4CONW0O5/Svbkxi9a0kF4
4eI8xya2JrX64hu+uskfIS+ptUA/NRb5nCTTSqcW59G+IcRst29bol3xslN1JELcYlOflaOQ
etDEdUX6AHeFeKXT8+jHNB3txgbs31RFzBv7rbAprHRR15uiA4UEKogouexLj9HTVO/RW+z9
qLEfRrZFfho4wJt79KL8ney3HODNPXpYzJKRQwO89S5jbUWSq/mB3foNuiwvqsmncID3fkKQ
AsnX+oFdIfBO50193R1REHDPnp8FWmfXJ+FTlj1/4hVuL3qa+vWYZIMFRaWJonA06SWrkyua
2kJTnq+6s2wqqcTsE3TS3K4b18wCVzxj8/WkfdxjUwu7boRGLomga9JSJK5aQed04uUxTccf
316FIea0ITkP6FetOFZ/BgRdP2v36XBl/9mYsghCms67nrdA4v2Yrx9Sso35AO9VetgKYfJF
McCblV4vtWf3Qwd4r9ILX2bWbLDdC7xZ60FpWSvxAd76CTksI5OP4YFdoCewXmi9EQQBN+35
G2mLFOheMVuEXhIsBXLqYvOYZBMWLlTZt07dV+BszX+N70uzi2reFBvybSpHdEKvkN5XrGkD
w9Omtq8H7eMeGRdt1qtGYxv1iJjbOo2hF10Ck3TUX4qq2IQb1+Qc/aKUjsuj20k6/pjVCrU2
s9rSFs797e3356Xefm+/xknnvAHeXM1Dl21ZJ5ADvL2aJ5yduH1it9fyarI28IT+RCXvTiFv
ex3Pt7vpOp5jl2i7iyV3ZEDAvXgOFqROLC2iBrIjdovqeGe9X49JNlGSIw1lwr5MJcODl9Xx
zuN2p9kAsd8bBVJKDsTFRUv68i5GbUcCxC02UZGrIKoc1sCcfNQW1fGIL05qJ+mo+L3xTWVt
LJp8ky4Sd5d1vFk6XCms2wW4Ze3b33W8v7KnXwx+57a/B3avwoupiuyQyABvVnj2zBxKm6oE
eK/Gk16Msg7YB3i7jrKedEce4L1VvBahG8nGhhd2gZq4CmKDEQIB95z54wjNpQT22rKmKovc
m/k00uIxyQYLALmYIBcSRMko5LhoRU/ehXvzHJswYu7dpCK3tG8HrVF6V0kwMDIgbrGpRUBb
uKnU2jqnTfDWTNpeCL1JNq69XeQ19V+3WnpiYYl5M50W8z+n6VhY92A4qvuOr2WFnk3tkX53
oYffYeqXPNNf4e57a4QgOTyw4A25QBT/lNFgx2RL9ABvPtp2IW7ZQ6sDvPcxEyiQ9SN4Ybfe
4xgnr5wUnAO89RsU7QWT59oHdvO2h6QoZM+BB3pFG+NVUWrEZsCdKAMtgGIdItM3YlaTHiew
ZE7ldOrmMcmGShOD7iqS6dkkmVKRS7oO+lVFaoqMFTZ1Tex7B+ZsG4WtigA5q+V+PWgf99hA
YRbfd4kY+RYs63Cyos6OJBfuM1NsfOWLTkxsvgNTomSRZvYo+N9vDp71ZH5O0sGCHFsvFN9N
GmTNCeb8NH53SfwP8hnU0mvWLvcA71V7TMXS4boHeLPaU39NJ8VeQPdqPcKillzVB3iv1mv5
qekDu/f+klrB7I/kC73iqJvPy1I4kjPwTpqBlNB43VzPSxfObVFksvDxh5nk85GVOTZUtDdC
8D+0YjoHZMWgqIu98zbGOTa9NDbuHTgifZMlQ79ohTy6Ens4cjNusQmx5zuKBjEcZS09HLVi
xPpK7M2xCdnmX5I/aNKrQbKlaZHYq3bexjhHJw4B/KdTiXr3XVLaXP7tNbhI7O32GpSi2QVs
gDerPCxCSZ+qAd6s8qiIZAeTD/DWuww1egBrcl7lC731W1Rt/sUkB9AHeLeap0KSNpU80CvU
3mnqhq/BI6cC74QHaFGxJoxq2FvSok+XjFmCnI55PCbZcCGONjOu0Huy14wnfTT+Xezp2dn9
5yQZqMUlJDWVZOHoecEKpXc6E/H1lH3cpBKZ8c3EvyXqmGy0iYuWHHWfN1XMsamlIWAV33wR
4bMFJaX0VhT3/S8+75+dvTnaLXybMMIfk8NRMLlFeiu938hqMNuUd2D3yj3hgpbuyXuBN8sA
K2E5mlQBL/Buued/a09urA/wXrGHYaiRvMsDvPug3kVwsnA0wEs6Gy8W4RFUgfeCKpgRjbp0
6pD0ltYl5RaQ0watxyQbepZbKvaOPWZZkoW9FdWWy1PcOTZWWMH5dJVmaMm2C7/ou+XeyKm4
xeYp96yTgZpy8kx6kdx72hJdP2k32YSpTJPGMXRNwj070LuiY8dvzvkp7uzN8V+Lge8lm9ae
zG6ASRvzt9z7UbNBKJL9+Q3wXpEHrtso2WU2wJu7uKKmkDxbHuC9dxnDQxeSQ+gHeO9d7lbS
/mov7F4RWm+M/wzwimoenffp4YiowHvpIUaNJKpfnXs6J24uNeDfJV6/OLudZFOryyJBRHU9
nD2CWmIofZUIPMfGX17QpbqOYNcQyXN1v2iJP9+vn7SPe2yq72af/QHkr5Tek2ancdWKw9t2
UdKbpCPRqte4sTWrycZDv2pJpx5clI6n6IAvlL0DsJhpT9db3516KzTeT7kNNkoePQ7wXhFA
rWC2P3mAN0s931Anzx0P7GahZ74TtaScP8B777GRC5BsHOAB3ttI2HuR7Pn3AH+31Bv5FHgn
MwBLj2Pbbmox4Zv8zktfIVzlVBw9JtlAMW2V/IFtStncO79oidtgOxsw+ZxkEw92pxggNb/z
2TnHJTL8WuqNdIpbbEK0kWu9mPBCVdks9c5KrY9pOmLhK+1kmv+6KTuovETqPZ1Erp+1m3Sg
QARGPmdmekv7FcyVAN5S74fdBrtl1/8DvLmcJyW5sX1BN+u7eC+nBd4LvL2UB8kPeGC3F/JY
si4iB3hzKS8OxZKu6wP83fpupFPgvXQKY5dE3T+gsWWHm4qtcRy8aMybZPP0Xfb1j3zlbVnH
wSWpLpelvCk2cQ7BpAh+h5ppjk1c9N36bmRT3GITSq2ybybI4mQw6euwo5Q3SSd0EFf2n07j
5FTJjkreFJuo5Cl3RWNpkFz835W8v7LfYC2YdQ0f4L0qIBxdJOspfYA392z5X0rp/vwXeK/S
I3/jZKs2A7y5locFe9ZX8gDvreU18/dcsroywN+t9UY6Bd7L2ujCQoL+GPqjmFVHfY3Wuyiw
TLGBOIRu3RA7VUs3GC05hG52UcubYkOlcyXXrs3FqyTZ0Joc4EutN8IpbrF5aj0l31QAWW9p
/+IlWg+vtN4kHemM1MEaStPk3YmrVtC5as2bogMFJJwgofo7BpNvtvAG+zuKPfoOz8Hkirti
rf1ru/slEwoHeK80QS3Skj+PAd4uQJmTIn6At97lBuFolvRrHuC9pTzshSEZ/jfAe+9y7VYs
axh6gBe8WPjKiWNEaOCdWAOOZCJUfwg7dEnaUsZFKw6TTwcaH9NsoKmpVKIGlhzQ4iWzs2B8
5ivyOcmm+b7FXw8RXSdWk8XGNlkBujMaMgI0brGBMCT3S57/Wjbac4khOcJpLNBjkk0tEcTH
lVVa2Elmk/hW2OFeTwJP3pwWcUC+NVDfwWWNLPyiv6P+/EcZ/LXszNkA7xV8Qv4+S/pNvrCb
5Z48872Tcu8F3nqPDSxcuJPusAd4bzWPY1uefAoHeHP/QNMSmVzJBoIDvUBUUL0QfCNJA+/E
G0ixaqbasZqQ5Sj5RSvOYwUvugen2FDhRmHyR9pYkz3GtKT/5HoWeIqNFe5G/h4zUs0aXtkS
01CsdJ6ngyNI4xYbKIyIzVyKE6XNsdbE2Z3XTx+TbOKoSGKTxNaatGQ5qa4pB8NFoM4cnTi1
8d+MRdFRW/LNFhe9Bd8awbfb5E+jDyf5RjnAm8+WI0kim+F5gLdrPajJzPUB3nqXfZvrEjgb
C/+F3lzci/bU5GowwHvvswKWbLftAC/QE8Bnh2S+Ao+ECLwX3iGEXaiRdtBkMFdctELr0YXW
m2LD/lIS8yUYVdSSxxR+0YqTfzuNx/2cZAO1kJkwWFT3klrPL+IVVim1nx1gfj1qHzfplGoh
90jBFR9lreTqCulKfJ4TM8cmLFz8KTNoCv5H2tF5kfHLRSF58uZEaGKLfBUXsZLty5gr8r/F
3m/k8wc9WWgf4M3VvV7yue0HeLMWqCWZPvGCbtZ7WAtkz8O/0Hv1Xo0UgmRlZoA363rTWIuz
wv5AL1F859U9GjERdMe73z+asrA26WaWXIbjoiXVvfN+wjk2VKJAIUDGxC1pUU+lr7CB6Xq+
Cs+xsWJizBGjB9CSq7AtiVe5FHw0UiJusXkKPuoxhV79YctqikWC77y6N8fGpZtQjckeVH0Z
R+cE34p8Fcbz1tXZm9MAhaJxgECSc9tx0Vvw/enZkf1Of+mo0QHeK/LiTNGSL+8B3ny8R4Va
NhrjAG+9yxQzyUkfvQO79Rt0We7aPDkyMsBbP6G/CqObKvk7OcBLOvbOi3o0wiHojmk/hvqs
0efmGqUncztwSd0I2C4k3iSbaAM0FEaz9GhZWWK0bacJep+TbPzVwCYYBshiLVmHpyUxJHHS
+qsn7eMeG5c3vs8RdQUR7qtJe4I62RX2h4HaM8X6mKcTE5PdZR76NjjpkelXrRjePu9A/Jym
Y027KnCrvpuo2XHnuQ7Et8j7Paz+ODsgPMCbD3G59NaT8xkHeLPW677NSWY6vLB77zFKOJMk
O9cP8N573Kn4aydZtD3Am4+Y/cGqSeOUAV6gJ67Gg2mEQ9Adx36MoU0jIIA48kyPB68o5z29
+M4W4Ck2UKz2Zr70ck3PmsCa1sNmF+vvFBsuWIE6+BdFoMnR7bjoW9vbvp60j3tswqtBkGs0
t/VGyY3SsvHg80GgWTrSqgLEniIG67P1PFlygHvhBTNHBwqKWLgEiAFmMwnKXGvPW+r9qNUf
ldrSVn8v8N71H6FUThb8B3izxsOS3n0P8OZ6nhaCpN/WAG+u6LXSIZnPMsDbK3raskr5AK84
tD3VRb72jnwIupd2EZ1TER2PopocJcQljfLXFb1JNjHn0YhUDblnk0i+v6I3xYYKKcS8DDG5
3sseQa84UI9H4ldP2sc9NlGbQ9Iaowy+oUh2tiyq6D3n+K4ftdt0fPeGzTeZwhrBc9mK3pI4
3quK3iQday5WjUT9PUDpEZM5L/S3zPs9LP/8vZ+3/AvwvU/4/wEAAP//7H1LkiQ7juSJhgIQ
P/ICuQg/RUutetFdi5n7ywDuxlhUiVnC+BiMyFcu77NSZjqc5kYlPqp/le05+dCkWNSB3dy8
BQWzpdsXdi+fp+i5S7Y4DvDmfF4roMl2pAHem8+jkMlJfsIB/up83rCHoJvWHc7vSJAMnXpl
a7dL8nnSLwpqU9FEaq4REqg2v0FlFWpXDG9f5/OmouHidyyqhK1Hh17ape3L83nDHOJWNJHP
a12AmZqiP8pbpZ0vVMRnwxET5+EVjJSyzZOL5P4u83lT4UQ+rzUPSP2alL1V/F3zeV8i95c1
U1hipPBnC/4lE2UDvLl50Ipl9V9e2M2pxl6yFg0Hdu8Fg1vRlqzmDPBechfieFST88AHeO8n
NC5JqvaCrqCedkEIhnMF3bEToKLSauPWyCok4/FFS2QL+0V9byoaLgoATm0MnAlK7n4aixZE
0+q5+u9sNH63ByQiNpGkR0os+mrqOYwrbkUT1FPD8VgYYjwkW3tdQj3PB10+JsPBAqZ+Z6vc
fXOSj5ovWsE84bTW8JiPRvwFygxVELKNUL7o78g8/6OE/lq2q2yA9xI94rxAzQBvzjRKjLxl
lZ1f4L273K0QJHONA7yXSkUGNtvlP8B7dxme0kItuc0DvYTyXYxoDgMLumMqwMWJV6ghc2Mj
Seagl9AKlAvF3dlosGPXKj0KsckJzVi0JNt4Lrg7F42G7rZEA78TC00WYnWJ7vb1MPCwr7gV
TXAk61artJCsTA8DL8nO/f5Jux8NiH9JtbfWBNIcaYlS9YW1yGw0iobQa2gmtfTezNXI34zv
Ryj9ZS9dA7yZ6tHTwT5J9V7gzVSP/UeT/akc4L1UT6gIJlnKAG/9Do17oaxk8gBv/YSdtFBL
KtMM8AqiJxcjwcMogu7ZXtSqRg2ato6Wy+2tcaVF5YuEy2Q0YX2sz+NXe1LciNd44vVTKbnH
ZDT+ghUNs9swX+OsqU1Z4Z5dEc81nWn4RNyKJloBRTs0INLO6bLynLLIv6Uqz1SQP6bDia5b
rkqtC98wQP5aU5LHZDjBQRHZ6R6iZjX/Z4nrm+r9IJ0/tfQ59gLvZXwChZI39gO7l++pv6Eo
mfJ5YbfucNNaODvQMsB7E3vsFFOSRdIXdu8OE4WwUFII6wCvqHziRXVteETQPf8OCsup6Ouq
1jjHr33RCseLK03nuWi4AJBRj1ous2Wb7mCNwt9FqmUqmlaIxDmrCGqvSRkEX7TGMZh/96T9
uhcNlF79RWL+X0PpkPvxwJL+TifMv33UbofjvBVAGvcWkntp+ZevdVd5TIaDhUn9UtGiXzWf
pOS3pvNfnxXZLfFXS3aA4And3KEX6fLkzWmAN/fokf+lScGSAd66w/6Odc6b7IEb4K3fIdVa
LFsVHeDNnzDEepKKay/sAg6Bp0MVfuoOXwi6p9XfsSFI79Xv8EnT10VDFSoXfXpT0dRSRZtZ
7ULZCZ462ef+rzVbvEjlzQbTmwIFfwjrrGQ0tGR4Vs4mmz8ftF/3ogG/hBkTY9wmLNsc5KuW
tOmdNjt8TIfjT29r2jwW9YjSCs5LJrX5jHw/5sPR9mwJDYEhTc8CzzmQvPndz1D3a5bUVRng
vVSvWqGsq/oAb6Z6rWBWh3iAt+4yMRQ/35M85QDvJVIhwZ19Dgd46yf0w7fU7IDXAC8p3J6n
WHhYQvAdnf5gFMpNGE1NeSejQIHzI3g2GpTOBH64i/asCmhZQsTbhUPqXDTk0TBwbFDMZGSV
X1bo2Djz/+2T9uteNM4MQgYvGlYtJPGy+n4rbsKVTgdoP+bD4cqNDLA5d00XbvVrU62P6XA6
+QoJ4ZcmmBwo9FXvbN5fZ3vfIPDX0yLOL/DmjJ6/k7NNvAO8mebVItl67Qu7OZ8nxV+xyW/w
AH9DPi85FzzAmz9hz/9OBngFybsQXeNhCsF3hPoxRpa1M/t1KKzjsxm9Jd15p72GH5PRRHaO
q5oZV7DkUMmqlB5fkLzJaAha4yrCYfyVFeShFf1ftZ135/GwhLgVTaT0mm8NOAVv3dIV2yUp
vStTttlwVFiqk7zQcrak/9EiU7arlN50OGoMzX86RuksxTul92fL+1lPim+8sHuZXgxXpKXf
DvBmpteLZGduX9i96TzFoj3ZeznAm9N5VF6Zq1Q67wXe+gkFuPSabA8d4CW9eeclNR6WEHzP
rsP/TAWhbtJb1q1jiY6z6hlt/ZgOBjo1rOD/pAVj6hKD10sd57lonqaNhGGeoKG9mNVxXjOh
ej7ww8MP4lY0flTUWgUxMseYPWJi1Qqid+HzPBuOVqkKFJN+ijVrZfblzmxz4USPk1/o2d8w
fptMOsP8Xccw6h+v7ndrkCA5Q7DgHbmAFX+X5mAHTE6uHuDNZe6Y8EhaKg/w3sdMQgsUcp9w
gPdmQNlqCX/4pHD4gd7LO02LZS8XA7x3n4nZz+xkL9MnekUWtJ/PrfAw0uA75gaohbh16sHB
sv1MsWjFWK9cUZapcPwu7F9SNyOB2rJp6iWDo9hOrXEfk9G00vw1y6jVwzHIbU4sWpIGPUvq
fj5qv27vjTQhM1X1Pz3Hv2iR/uBpbfhjMhrwr7n7r4aY1CrlfX6XqEP2iyzoVDhxQ2xoYlVN
JZmijhrj35Ec/wcJEFqhrKvkAO9lfX54AmeNTp7YzZxPo46d1aR5gTdzPumlYzJRdID3Mr5O
oRCenJk9wFs/YXfGAz35CQd4Bd87nYX1Q3jYafAtiwMphjGljNg02Z/1XPPVdG8qGoraTO9S
AdEs2agZi1ZUvU9nJR6T0YgTpFqdUJA/PclgZInAjrO93z5ov+5uTQMAv1G0BmpJgZ1Y9NVs
byoa520YuV2S0LnMvgkWDV1fTSnPhYOFUbCZATkXx5zMJU6WRN5s7/vFB8WfxGRT0ABvpnm1
CKbzUi/wZqLn54YmmwcHeC/R00oFNJmD/0Rv/Ra1WUHLCiQe4M3JPWpFJS1J8wQvKXuf+xfz
sK/gW54CVkA6OjsKV6tkQLZE4g71NJqPyWi4sHbogiaMlHUW4RX6Ou1ULegxGUwLvb5uCOS/
wJ5UkWhr5PpquxhiGeYVt6KpJUSZoVXo1SRJ9WLRiqr3VSftVDTg18vqL/AK7FSvUXZieYkG
OOK5ovlcOKEtEwPl1YLpQZrqvZ1FVlG97xIf9FtxMmFxgPcyPuFCyaTUE7qZ7XV/P2m2lPsC
72V7kQirkrR3/UTvZXu+caCYTC8f4L37DDFEk2x7GOAVib0rtjecK/iWn4CWaI5XEn/fCyXH
WWLRkszeRZvjVDj+LISrrLM9X1fT2tlL2hztdALkMRmNFupNqAE4o4CWNNopvESipp1Ris9H
7de9aPxHEPrMfgNvCGzJ4kxZMQdWz+fAPiajCe1spA6mTSBSfFm+tyRTeZp3fUyGg/4bUKvs
BNZaTaqC4LuQu4DvbRcgxGKUPF0HeC/HQw7/iOSF8ADvPf85jLWSmdEB3szk2c+BZGf8AO/d
5V6LUjKJMcB7C8zaS89WOwd4AZFAvpgwGLYVfM+2glWxKVKllylVjkisSIOpnjt6zUVTC1QB
P6o0jOmySvQFVoxgm53rEM5FQ6UzV+2k3FU1W4xe0SjgTPliaGqYVtyKBksHCLqFYPI0vM2N
x69gRXRF8qaigSJdEMi5vf9uWtJgF5Y4UzulvCB5k5uD0hF8Ua2RRc6SvKnr/5vk/QwVwqwO
woHdywHISvgeJEeWX+DNTK8XsqRt1QBvrtJrkazC3wBv/Q4JXiOBuZPtAG/9hFyhACdFxQd4
BdOTi275YVrBd4wEtETfD2q0ZL9yOCmmV1doEKpcaIZMReOkDauYtV4xXSBc4dyKdspaH9Ox
xPi1VrXQp8n2rKwxJ7vkecOw4lY0WJqGcbN1vzxCkoPjmqkMOk20fkxGE4yN0RlXt2bO+HK0
dRHPA7roE5gMpzH7xYhbDfHJpEhVrHoTvb9M9PYLEFJaZvqJ3ZzLCz285FjmAG/P5QFlM94H
eC/DY983zppAH+DNDI+KZsdZBnhvLq9hqZxVbzrAX53LG74VfMdLwAk8xxFlys64kg16vmjN
5O2FyvRUNDEL2BARSEgsmw0uuITjtbO9eUxGEy+HsIsz50aN0+2GK3poapWL3oDhWnErmjCv
wa4A6JeJ5FB0rFkSzLk58Fww8LR1BxNlY3k6OeYo3pJRjNOp6Mf03vjjG12gaj2S+tlU3tTZ
+mZ4P0R90JIztwO8l+pxDLdnO8sO8Ob2vBjIynbnPbGbiV4tnKyZHNi9NA+tZOeBDuzeNJ6z
8/B/zx27B/iL03gy7CrkjoWAOv8UaNH9pa0nL/C+aAnJ4/P0ylw0QfKi4iS1hp9XmuStSEra
RXZlNpqwRRFtDRphUpCkfn3BVoZZxa1osLRWAaiDxPRCOpG3Rkrx3KFwLppQEYybBJCz7+iZ
3Kk9SHKeM54NpzUNEu6PG0S/QzaRN3Uu/HSaR18hPpjUrlphNfNHi/z1pITeAO+lnlUL1+TM
1QBvp56M2dfrAd66yyHJ739rMs34id76LSrFwFz2STzAe/cZlf31y8l08kAveLlUO880yrDT
kFtWJ1isktMD9K9Rs7qFuESXGOVUyPdjMhyn+52YVcTvnZRsL45FC6LpfJace0xGY2Hiox6K
Pz7IyQSQrRk3vZoNkeGmcSuaWkycDfq+hPBLMtcYi5aw0N8+aTej8ROwMUCvztsq16S0a6xa
kmu8YKFT4Tjb92sUij9papg2MW9v2ZdVdO97RP7Ur0XJzMMLu5fzCfm7OWt3coA3cz4piklz
zgHeuseVei9Uk/0Dn+i9lVvmIJpJmb8DvJvbx0Bs1sJwoBfQCsJzezsZzhpyy+1AwvUEBEk6
UFL+MRatmQc+l3+ZC8fvKH4UE6DzPT8Yc6l1KrIi89j5XJRjLppe1FrXzjVcjJOXyb7G9RdP
Z7U/H7Vfd/fGYg6YwmWnSs8KOy9RsznvufuYjCa657A72+tBy0GyoyIr+mDi2f7do3YznBov
esLW/U2lNe0XNKe38eZ8P0HqL5oJ0lJ/Ad5cXdYCaaZygLfTPbBkXmGA99I9rf4TzeqWfKL3
pviqhbJCUurvAO/dZ6utJInRE7qAS/DV6TtMIuSmg0dH8JNKBU2zAl+6pL0LhS6I3lQ40URn
LboI/e3ESQUmX7SiYN7lfCZ4cnOwIDsHR9+hSLlkM6+4RtT5XOlPhkvErXBCtI9AWwwjNEsm
khcp/aGcq4fPRRMevg2jx7o1vyMlC4iwhoafNwA8JsOJoZzI6okgsyRtmX3R28d4FdP7LqW/
BkltiwHenN9rxWqyW2+A9xIBBb8lJecSB3gz4QMnwsni0ADvpXtOKRQkKW12gDfvsobCYNrj
7ECvqOheqP3JsIqQWwL+0SLIqpW6v/STXhG4qq8Qznv658Kh0jgqoKC9dUsmKWiJ9QW2U1eS
x+zm+AvCg0DnFAyaFOmJRWsE8i5KusMs4lY4tXgwxlyJGvYkh61LTFZqvWosnIrG6ZsiYNeo
LiRJUqz56oLuVDBYrPk9qXWuXI2zIj1zSoxvyvfdYn+SPLsGeC/Nw3AOS9YyBngvAYiJ2pY1
vTrAe0v1Pa7+yfbHAd76HRJY2HgmR0cO8N4yM2BsXO47HOAlmb2zt7sfvMMlQu5ZXrRQ5qh+
VkHWwIMnu3X+leKdGox+TAZTC7IBaLUaHbHp0ZElFA8umvamoolytEbHHjszgqT565py9IUd
2OeD9uteNFgYhK37dUIlq8MYHmILoqELU8C5aGLUV8FpkbNv8dvEzskRoItWgcm9cbIqzRl4
JMST0fiid8/eAor3XVJ/jZLNZgO8uYLLpUPSCm2ANzO9MEtKZkVe2L1JW2xFLSvqfID37nHj
wpItMB/gzfXlFhqNyamvA7yATODpcKAfv8MdQu65Q4SZrJMidCoKaSGYJUYkeio28jEZTQiH
VAMh6v7U9rRw8BIhmH5B9Kai4RISJl1JW9Ws76svWkEm6qmszeeT9uvu3rQwhsBK0IyynoCL
LIbtIpU3FQ0UMQxe5MSoczacWLWiHI3nmkOzmxONOsCg4sd6WnF7LonyZnrfrPWHkJwmGuC9
x3/1K4Qm0zwDvJni1dIteVV9YTen8rRY9ix/Yfcm8pD8kphMNQ7w5kSelmxp88AuqdVe1M+G
L4TcEevn0qI3vlKFzq3nAuLJvpx/K9Ve5PGmoqnOOzsxqWpUa7P95EuGb9tpHf0xGQ0VYQ6T
C3HmbcnsSiz66jzesIW4FU2k5AgUtSlwTU7XL8rjXUrATEUTKTluYE6DlfxylPbs+PJE3uTm
QDU1EYQeXYfZRN57EGMBvfsuob8ulpx3PMCbE3la1LJD+gd4L8sT8PMmmch7YTd3X4pvW7Iv
b4D37nG3gllF5wHenMizopgUxBzgJYm8C7G/4QwhNz07CDu2FooeWW6kS5JFqHrRlDcVDfqd
qbGoR1QbJufzcYn2hf+Mzy2z5qLh0NltjXsH4OxbmZckWa/F/oYxxM29adqotl7JglR8aa//
v1ZsTzWQPyajCXc2QnYKSc6OLDl/H6u+OpE3uTlVaqt+2XNWbEkdXZzszf3pTO9LtP6wJpu4
6oqX0bIBkf1qf355yqv9BXhzy6AV03TL4Au8nX8CJqcaBnjrLvsj3vxFmByU/ETvZXg9JLGS
v9kB3voJDWuBrH/hAK/INp4WxZwZDOcKueMn4NvburH13oUxeZS2JUcpcr/IAU1Fw0VBwWrX
xph96/uiJcVku2jXn4zGWLWLmt8OslocvEgcjy446HCuuBVNGPRhKBZK80tCdr5viatfhXbu
XzMXDT5/0kTiWwPUsqRthZN5fWYDr5+029H41pBYPGadkzUHnHTj+ekU9D9I6c/8KU5mowZ4
L+MjLpAVBRngzYxP/GeQloB7gfcyPsMocmQlqAd6L+OTWiT7LQ7w3n1G7PGSTKa1BnoFS6rn
eUcdRhZ6y/ohakutcuUOJFnhotna0r+VmM9Vd+fC4VJDLcU6ScNac0VZX7SC9PUL64e5aMw/
GJuFQA9USus7r4imwikh/3zUft2LphZlUlbsUPUpuJwifStmES/1neei8Z8ANIYG+FTIy0qm
LKGweFr+f0xH4xclJ3vk/2DyZ+Nr3gXmRZxvt9KfFuQklRrgzWSPSksWbw/sZqrHRTWd3HuB
91I97uI/0OyJPtB7U2eCpXPyWxzgrZ+wdz+Ako7BB3ZFao8uaN5witA78v2hGgzmHK9WBoNc
0S8WrSgv83nCZS4aLo43ATPQdIoiFq1I7V0occxFo6G2TYghGNw12byvS9S2nUmc7c3nk/br
XjQYHrvgNxUWxJZMi+Mii93T383HZDRQml/f/F/xvUkPLsaqFeGcDlg9pjcHDJsYa20xl5Ql
rW+dv1U877t0/qQlmcAA76V7AoUomfMZ4L2ET/1HDdmhkQO8dZf9xo5FILnNn+i9uT22Ij3d
V/AC791nprjXZptEBnpJbu/iKB5WEXrLx4NKqKZQN+FG2U4vWpKjuJR3nguHowseFVVQlCxb
Al2SqWx43lQ4F00rHYg6ILVqWUYei1awvt8/ar/uRVNLqMgBYBTcKakmF4sWRFP53MdjLhrw
exwzMjz9nZO66LFoBek79b95TEbj73mSGlrV/qNpySwyTg4qvUnfdyv9UdLweoA3t+1FCjw5
+ffC7j7+C/TkNW+At+5xjKs2yX2DB3brN0iVSk2r/B3gvZ+Q/BjtyaajAV6R1evn/h06LCL0
jmx/TJNWJPO7BktLXufXjKA6Cztv2JuLxumAdL+WOJ1mAEpziBVZvX5VUZuMhtQZXmQozc/f
tHnWijGL88TR55P26140UfAHjwNA/KWS7R9Zwr1D1+R3T9rNaJyqiVOhbhY5V0veRxdJOZOd
0dXHfDitO7MzIGbo7Wv56pvh/QyhP+YbQn8B3kv0qhXqWdeJA7yZ6jVnb9kRqwO8tyfTwnme
k51wB3gvlQp9wZacAh/grZ+QW3tqY+V+KQd4Bdk7nUL1I3hYQ+gdwX4uIuHZ0SGk8ZKZ6Fi0
IjfZz5V256IJeWZsHZ3pKdbsjPkiTWc692qbi8ZvMV07GqC/yjg5j06F1mg6n09n6LCGuBUN
FhKneuqXC/aQshPCKzSeKuFvn7Sb0TjPYVAW7KHDKOkS7hf3HT6mw+kNhchE1IQ1K20zN1v/
JnvfqvVXS9e01t8LvDmdF+OM2fmtA7yZ5dUilG3VP8CbE3rdD+mkmt4Ab07pPb2ekxm9J3bv
52Mu4Sma+4AH+KsTesMbQu95Q4gJVHV6F91TyYiKLJFzPhWz+JiMphYnds7uyAgp24kai1Yk
9E61GB/T0TBqD2Vlk5p1fKxr2vQuE3rDG+JWNJGbI33NR0N+ZHVFPs9/gb970G4GE5k5EGl+
O4IKlmwNWJTPwwuHmOlwemsYlnnAqslqOhSbuk68Kd7P0PtrWaY3wHuZXgxZZLNlA7yZ6Tk1
qkkWMMBbd9mqOgFOqqEN8OZ8nhWGZB/mAG/9hH7z9bdjUgJ1gFdwvQttZx32EHrPHqL5kQWo
5lzFkj0Ri4YYpF+MQ05FU0ukvpBqF5LkDEOsWdKbd3EATwXjjNqZHiApmRJnPYUXmUP89kH7
dS8aLMxdRRtCGPFm03m8RDrmQtp5LppQJCBDI6nq3CjP9ZZIO19NZExuDqjEjd5fMNzTNrx/
5kTGPiL3P//833/+v3/+73//4//81//9x9YDKqmatZcaZccWFryNF3Dw71A8rE0Kt6wx3QHe
XFH3G17aVu0A733MJBxxOcnAD/Dme1YtDZMV9QHenFHv+QbUAd77gjN2Up0UjRzgFQz8qs45
HDz0noMHVWSmEFYPi9Rs1XaJS7JdjKpORRM0z6o0c1ZUJekrvIbmYbuSvpmKRoqZdaeszelR
42R1pKzoLrmQV/l80n7d3RuLLgesHotaun1yxQTh9VD0VDR+tGjI1FfpFNqauXB81Yr7EV9V
1KfCIafgYflMDZyEZ5MfvuhPpOA/K9v6jYKHtYf/YbaMc4D3UgGm0jTbQnmANxM+9dM9mbYe
4M2Er5XsqMeB3Uzqo3qbS8kc2L1kL7Tdk8zowK6genxxAA8LD73jq0ClsjXnEp1BNJvQm7NV
+Ne6ul7I30wF46Stqh9YPVrAWro/j1cMQpucsfDHZDRSyLdFkH3bgZOlaFkzKHPJ9IaBx829
MWfhrCiVIG+TvESn+5LpTUXzZHqRb40hGa1JzcZFTA+v2nSnwvH7fFNtrZF/V/kp9faek1nE
9PbOTzBJaZAdhz7AmyleLcLZqvoB3kzxqGjWCWaA91I8lcI9eQkd4L27LFxq8mA7sFs/X69x
Bufe7Qd2Bck7nYP0s3d4ZOgd5wJ/+Bp0BGRhqD3ryKtL1HtO530+JqPBoiJ+TvVq7P/PsrwV
7wc0veienIpGwwScwlSiYuekt3lZcVusYBfNk8Mi4+bW1G7S0bcmnLmziipLxn3owr5kLhrw
W6WTISRRjd9ONp23ouu4IlyQvKlwoquESMwodsiyMuNzF/83yfshGofMWDr15FTkAd7OApiT
wigDvJnrheJvdiL6AO/leua3sZr8Dgd47y5rXDKz86wHeG9Kr1NplNzlAV7B9y6mZWzYY9gd
04JIhxoTQhc/RpIy0LTIr87OovmYjMapG2vUoDimMihbv9U1E9FnIxmPyWjEv+awYamta9Ok
QoAUXTIRfUH4bNhj3Nyb2hVjKoMat6zD0yrC99sn7WY04X7MTUJxNEhfdoJ4jWXyaRfHYzKa
6reEKoQxYoZZTes6ebV4871vlDesCgVFs2frC7y5e4v8FdaTz+AB3svxOIzps0MyT+zmsrxT
IkhOQw/w5mZavzzUrIzqAd76Ccm/FrNkp+gAr+BEp605fu4Oawy741dQn7JzSqytA2Tr5Gsk
n1XPx1TnosHITAChNsyOqa2ZkDE975ma3RirjIDoPIJqckImFi2gEPV04PbzMft1f2OEO6hq
yOhl2/NWaNM6vfvtY3YzGij6dPlxMqQEyeYXWOTAUi/o3eTeiF/tpEoY/ViyddsXve2IF9C7
b2nMUyn+ss+yvBd4L8sjLQbJDvgB3szyWsnq1h/YzSyvFc5mGgd4M8vjQtlupAHey/Ial9AD
zLG8A7yATFC7OH6HFYbdM48AENPegh71JDWqi2xK7HwSei4a5wXAXJWthwdxtgMMF+SK/LJ2
1gH2mN4baVGkE+beszMydU1t8JLoDSuMu3tTq2C1DgIk6b1ZQlvlvHA7F41zNmzQiDB+2pjk
rYuY3vmc+mN6c5gFBNVfBi3twTA5wPRmet8obBh1L39gk2myA7w5kSf+q88eRQd4M8Wj0ik7
SnaA9+5y60Uh6aQ2wJtJXi2Ylf8f4M2pPCq1JXd5gFeQvKti7fDDsHt+GIA1Cpto6GdVtvd6
Ccm7TOVNRROcQE25tSZZy941CaPrZN7k1hhVBqcSEqa92Y4pW5H+wtPK8+eD9uv21jxluIWM
sfV0onVFrbbKRa12KprgeKqtt8r+ArJkW8CqbB6dSYI+pjeHu7CxdDSzlssbRwrwzfH+Osf7
nmxeLybZ5vcDvJfqccgpJi9PA7y5Lw/8Z5Mt2h7gzfm8MJpLdl8O8Gaqp8VPhGT54ABvz+dJ
z3pHHOAVfXl6QfWGG4bd84/oVqMlD9Qkm4X2NV+dzpsMBkHFJMYWgCl7YuEK3mp2UU2biqYW
ET9/gfyLkp4kR75oiVDyFdUbXhi39waiabKHy3Vy0G8H1ZuKJqiekR9/5ASWIDmQtYzqXdwq
JjeHq4SSPdeqNd0zOTel/tOpHqWp3o0TI9kJt6IH7k+W9VNK3mhf2M15Rme8mh0KOcDbyaff
PbMDwC/w1j0Onb6s4fCB3bvH1Y8cyWq8PLFbP18HLai5xMKBXfBCwVMJamcDw6DD7pmnEEsF
E6ut9aRknC9aMUAhdpFhnIrGT8Lw+QtbOVRKZtFj0ZIU40VtbyoaLU4wGLmF+V7yt6Br7Eau
NF5s+HPc3BqTLgYduVfMDup8uZjfXDAh1sJVmz9r2CDPOpdIvNTTxPxjMhwq6HdP6LUpS3Yi
DP9INe2flV78Zik/w2yO8QDvpQCCpbdkbmeAN9M8J7+c9NUY4M00rxXOeqsO8GYy34plcyov
7NbP13ovDS2p5neAV2QYL5SbbRh02D2Djqr6fM9DQ02/5+uSFOOFT95cNM7aQIw6oL7GAXJM
b0WG8Uq4eS6Y0GCOZhgy1tqyskxfL9xsw57j5tY4OerVSXi4dLRsLntFL5BfBS8yjFPRhCcA
ABohhgBeMi8Ca9QJq14ks6fCoQKNhRphM7Ok4nkserO9NWxvv5wft6wd8gHeXErWwlmxgwHe
TPO4aJIBHNi9JE+lkCRHawZ4M5WnqK8nmfwTuzebZz3UyXLn7gCvIHkXcn42LCDsni6/n7nY
uaIxQ/JXRWsE8PjCnmMuGixRp6TuwYgfv1nNuCXFG2sXLG8qGi3OHjgylP5VaZLlxaIVObAr
eZfhAHFzb2pvlbT67vSetudYIu9Sr4SEpqKB58gOIlcRqJWy9sFr9Pzq2ZTLYzKcWir7CmVo
FTjZTlIntdvfLO/H6PmFRE+ywj3Am4lAZHCSL4sB3kz2esla2h3YvWTPQhEimfAY4M17HAJ9
2RGWA7yX7jUoIElZhAFeQfeuBkSGD4Tds+h4ytAyMZllE0e05NRCuZrNnIoG4xCuYr2R+Wmc
pRRLorGrqtpUNFqQKvgp3FVMa64JUtcIpFzSvWEDcXNvahdtIUVNZElTi2V079wQeS4aJ25W
obemCEqSzI/AIrfqenbre0yG48wtJsTUr0gNe9JAxRe95fz++oTIfjm/Jtl62QHeXNCjkOxK
lm0P8F6Kx1yoZ5trD/Dm4rx/LZqV8znAe79DtWIi2dGQF3jrJ2Qg/0uTuzzAK7JgV4J+wwbC
7onzA0F9quiGplf27b5E0O+ZVj47eqeiQX9Y0TqpAPtZlR4DXmPRcZHTm9wbp3fYe4jxGOfd
sZbQoiupl2EDcXdvKrUqVAUU0l16S6Re4GoKaSoaiH4baK1LByJMvk5hSfq4Qj3bnMf05gjH
+G9F7FKTj5oveuf0FpC87xkD1pKeD31hN1duxW+rycLoAG9mer1gdmJvgDczvVbU0o7KL/B2
pidZ6d0XdjPPi4p7sglzgFfwvHo+mdmG/UO7KcoP2JzhCZNq1g7FFy2I5krtZS6aJ5dAYed5
zv2TRiOLtJv7hUHW7N4Y1to7YtSh89rNC/oNL3leG/YPt/cGqLbWDGWvoh/iedZ4LpgY5m2i
HQwakCWNqn3VkkTrhXbz7N6IX49qNB1as6QVmy965/L+Os3br+jXsmWoAd6cy2O/eCe13gZ4
M8Oj0noyfz/Ae3e5db+4JYtZA7yZ4Wkkv9IqL47dzvAQ0pm8F3gBi7jS82vDAaLdtObAaC4K
/zqDfCZviWjzae7rYzKamLpu/nuSHqQ1qwj59Zm82b1p0BitgbFaUhfFF61geFcqL204QNzd
G0CpGklJM0uz7xV5SYTzcu1cNEHWmHoFNY7bRFrQbw3FO8/kzW6OkJEKhtdW0jo4sn9vhvfX
Gd63JPIM4jKcvNAf4M2pPI3x2fwQRoA39+VB8QM5r+cX4M2pPC3SslMOB3gz0esFOen2OMCb
qZ4VSp69B3ZFX96Fml8bDhDtnix/Nz/Vq9QelurZ8dQlcn6XqbzJaLCyYfPjFxGSqjerbNjk
4vSdiqYWC/8HM9XK2R6LNZm8S543/B9ubg1062H9QAbpIbU1PI9Oc18fk9FEKk/DWJlBwX87
6Yrtl6fyJjdHwJp0ADDKWjf8XW3YvkTND7MaTys6zP9kPT9L+3Ic4L30s0JhwuQnPMDbK8ma
dQsa4K27HCp9KklyN8DbO0ObSlbr5QXe+gk7xkxUUrdxgBe8WK50/dqwp2h3PANCoq8rAvRO
nPQM9DUrUnN6KoT3MRlMqOJ2RqLGUjGptjarintjLmQuGnXK5j89rBJK38mfgy5KzV2IvbRh
TnFzb5yhV78bCLaOSaWpRcJ+2M9VheaigWLcuLMwh0p2clBxkdgLw/kY8Fw4VPzN0qtp9+3J
NQzGkr8j/fyPEvZjzdYvDvBeHqB+0rTk7MAAb042cumWvbAd4M1sr/nXkuT0A7yZ02uRrE/c
AG9me2Hwl6t7H9gVycYLYb82/CnaHdOAMLDz97uIxAigZt/zS67EqhdH8FQ08UKq4O8k8mNY
ek72OBatIHt2cQJPRSOldQsNZ6euof2SVPbrX072hj3Fzb0x5mqkVrlB8r6+SNnvSsV5LprQ
YzZqrbJor8C5Rw3WyC7WU0fwx2Q4ztwovEMaqUjNepyXuUTKm+79BGU/bUnVtwHeywAkFIWS
rdIv7Jd9vv8PAAD//+xdQZLkNg78EYMEQJD4QB96/v+fBarEOeyG6BSXzR7b7XU49pCcqSyp
pCQIZN6pvKIM1vQu8FmVpzWJgBpqgA83DviNhVbhB/isyuuUugsK0OzlDd6h8ybefn3kQfRn
Nv2qzXVE1i7R8I56+20xcK6Tt+8Sm5KqcbHazF9Z+MllXapOPPD2W2OjiVv07XMVKwbebb5o
h5SYmb30EQjx8NpQ6AhWEnI66MHlFrMXljs2n4tscqrKjf2nE2fLYIp23pTfN7H2W2MT78n4
0filUYWdQNKajdqPzPuTrP0ErEgN8OGqXk3+/APrPRf4sN6zZB1NvLzAZ/Veo1QFdB8c4MNX
ObvIhN2H5PD5bY/pFPCZOMA7tN5sUmQkQvRnNv219V5Mqr+GscLEJls/0cn7d4lLSUrNmXBl
fzIJeny7o6lrfny7xOaV5ef3juTOaqARni7GZT1ReiMO4uG1IatExLllzuCeYpfSu62Efy6y
CT9mK3Gqnruilot5y55irvSW2LhoY6KmfnW0FgLDMH3Rj9L7v+dEvsHVD7TCurDHO7eagMbS
A3y4P0+SZNSF/gIfPpcPq0Mww2CAz36H6pIXnke7wEc/oeSaagX3GAO8QxNNPP36yILozwz6
M1m36vKuGjp8vc3Tb3Jmu8SmuLxRX8KmLrjA6+OL9hg3T2p5i9cmJoHDNi7c1hp6bbZMAk+9
XkYUxNNrQ1xrYfPNImqCt8nshWXSCrrEJieXQpJNw9HPd0hog57uaNCbTgIvXpxapWZpkXLD
YIvej6ff39vTT9DI2AE+fGpbU0fPHAf4sNaLyVS0O+8CH9Z6PamitdALfPY7bOTvbPCcaoAP
az3zrwUNs7nAG/QE291Jp7+BRxBEf+bOnzP5Y56oh0oCnYD2+PpNXV+W2ITri0jurTbODDZN
xaKv1nqL18a3qp2kM/dSO9afR5vCXWdab+RAPL02/of6vWbSW0bd2b/ev3mNTTgxa+nZtxQR
WQvOnZ/QeosXp7Lv9JQzkRp6DPVj+7JD65029mN/eqMP+gt8uKAnybfruLFfgA+LPE4GP8Iu
8Nmr3C1JQw0kLvDxgl4DzbIu7PFyXuvgBOQAb5F4k+PaEQPRH0Z0lLBbs15zYTiAaYuxn+pd
o+HnIpso55myhUeZWIdlxJeX8xavTS/WrPvNk7lX9Bhtx6Z2bvgyUiCeXpucNSbGrVTGbbV3
HNhOJd4Sm5B4NUZKGlXjBhqQnZB4ixenCvVqvpUgRh1LfyTe39zZD+yauLCHi3maRFFPugt8
uCkvJ8ngY+yNPVzK01QJ/CkP8OFSHsdsD1rKe4PP6rySk+sJUOdd4B1teRNfPxsxEPbMnN9a
kab+BtZi4DjnJl+/WSlvlU2JSKnGLTcWuCLx5aW8NTaUfI/KQiS+0TJwrCsW7ZAS/a756/ed
9vH02mRrrr65lEZwCsQeX79y3x+wRiZkHvVeODd1oQeaVG1LYrv39Vu9NjVyTCRmfWLsHpV5
/8iIDvoKXz+wMnW6JoW2Rm14Pm6QxN/mNcigDdQAn5XEFBP8YIXmjT0siMPuDHUavMBHr3FY
mPijGQ1dGejzV5nB8+0BPvoJLfsrHkzxvLA7JHG572S0kZthT8IMehQLWy2WWxc0Ga3vKRbW
fifwPxfZ+M+pNnW1UtWFPuw0uMd85q6O+2uRTE1WM2tptUUwGnavxaIdh9v9fvzdRmrGIzaS
mF0P9+p7lo62ZcaiHRpyYj6zxibMZ8ivjt9oUSvEnqWxaMe1mQxFrbFh3xS6Hi4tixTQk4QX
N5J/uiD+VzkNagbPU97YsxpAXp5t4AHtBT6s9TS1Aqb/DvBprWepoz/p3+jDWk9TVXSy5gIf
/YRdswseMMp7gHeovX7Xf+8v4RGeYU8iDVqyUkhN/UbMGdTXsWiH2muTl/ASG1du4f3GXSTa
stAkLtlSAL3Vrr8W2dQk70TfEBUMzhT5oh3Tr9TvXS1thGc8YiOJalFr7BfGCBSvseir5d4S
m1BuajFUJOGWDZ7IbfIa5DzRe0t0KJlYWFpqI2XYhGZtZ/Ej+P4Er8GOzo4N8GGtF2Yo4Ozq
AB/Wepx84wpKvRf2rNLjGCxXtPA40IfbGVrK4ODPhT1b02suLgVs/B3gDVpCaKLzRkiFPUkO
6H5xtdfWLLs+KmhVr+846JZb1fq5yMb3nk3Ut3hNCxN80L3FOXHmNbjGRhOHoQ5lLZLRkDTd
Eu4ysS3+fad9PGPzMjrwy9Kb8+lgQyNvmk9u9w40a2xeDjRNGrk4sm6GVZAPWNCs0aFEEvM3
zQrB1hCx6EfnbdJ532U2yIzduhf2sAyQxPAg5QU+LPZimgJsZx7g03LPNaah3q4DffY6q0s4
QZsJLvBZwSeaOjg1emE3SAq2yUt4xFTYk+yAniqLVa6qLBn8xmPRDrl3e+75ucgmlFsM81rt
VRTu0twj92anuEtsajJqhVpuRNwJeyz7oh3nnqSTst5IqXjEhlPuVJmaslGFkwl3GLES30rx
z0U2OWnmFpMk2QozSCdW7ZB7eVJBXqJDyXcUGs0ctRGaVkM/ESIb5N5xx8GSfDOHvlrf4LMv
/0jcamA5aoDPirywEWxg9+8be/QaV4kWC/AbHODDDbVxkACe0A/w0U8o2XUv2K9+Ybd06U3G
CUY+hT3LDmnVKmnVoh1VrLwlprXobbvR5yKbsCxpnUscRYuBzri+aI+j9KSet8SGUrMXD4ng
dbDVIhZtKRlNthIjn+Ihm+x0pGqtzdUEOm69ReDRJDtkjY1LNeJWexfuORcwpiZW7TiGngwo
r9GJWePwG8w5N/9dov2tPwPKOwTed/kNagYLUQN8Vudx8x8/+Jh4Yw+rPEv+XEGdpd/gwzrP
L5s/oUCd9wYf1nk1wlTQ8ak3+OgnZKPII8Nk0Ru7Q+dNMuJspFPYs9wQVbLCqubPeUZ13o6B
8FLrROctsXHJVqLM0f1NWDOY5xCLNrB5JUPfvXyX2FBSzv76tZKbEGwStCMHhfxH9Vd32sdT
Nrlm13hE5rcxaF0ci7YU8v7yTnvIJhQbuWANbwQuaHruLp3HdwPXvxbplOR7CZfg3KOHEo04
9UU/Ou//1nmnvQYp9QpWKAb4cCGvJrDl5g09LO84+QMZnG+4wIflHSUuYNfbAJ8v4+E1vOMF
vMbgcMgAf3UJb8RS2JOsgKjGdYlcR3+stw5q1S0Tg/MS3hKbqMYVq9VypgZa+56o4C2RicSQ
KKywZCpWUGW3JTFkWsEboRQP2WTXQFIlR9g0nk2zpb9QJh15S2xcoxVrFH2s5A9GQuN/v76C
t0QnXKR98+mMcrMMNn/+VPD+xhaDaql3MBN2gM8KPIlRAPQs+QIfbsfLSdBU9gE+XsPrqAwd
4MMir6dS0AGWC3y2htctkYJHNAO8Q+r1u+27v4FHKoU9iQrgpMy1NM7GXRtcxduSDlcn7m9L
bKIg11zt+caTa8YTQ3Zcm86TdrwlNpRqV61Se2nSwHMB2tTgf5uY+/tO+3jKJpOWEK/+TwXd
e/bkEM6reEtsXlU8I+tsuWW083OT1ivlrsT6a5FOjKcT117Nd0h4OPNa6PqfrvX4K3wGwXip
LcFS22ZCzjv6KaGjPxf4cIEx5idAc8YBPq4/GY3efGOPXuMS7jdChrq8XOizV5liF4vuMi7w
0U9o0hLs+j/AO/RnnpztjcgMe5Jj0BM1alq6GrUO+qLEoh36s01UwRKbONeKjie1YgyX+hcP
w/6n1jg52ltio37bUAy2kMY+Gqs1xqId1bmZqd9IzHjERhJX3+qw9GyE9inFoi3HrhOXlyU2
4fJStZqoqIUd5kmXF5m5vCzR4cTF2VBrmQ3ujklrrsx/uv78V9n6EaMFxwt8VgrU2IGCpyxv
7GG55ypYCqr33uDTgq/hbjQX+Lior6jVyxt7VuxxuLdgj8QLu6XUeHvYZ/lKzYj/80TqZd9x
uMiLcLTOWI3BF+0oztX7oIlFNq7aSo5wYnNt1MBnWCzaIvVu6z+LbNSvTWO/6E2Y0fZZ3XJt
KNut1BtsPp6xkUSdRWrxf7qBqRmxaEdtrt5aCi2ycdEWcb4uw3NuGfdv3iFc5XbD92uRDSf/
imIKqWT/5YBFbV/0o/Q2Kb3zfn6uOcDd1gU+fKasyfeE6JnyG3xY5EnSjkbCXOCzIo/Vrxzq
dnaBDwv56E8Di/ADfPYq56L+CiLwSxzoDXJC6PZU2XIZcuJZUod/sppNtZRIhUA9/faYvNzW
WhbZlAiVUW4uKsi0oYdjW45y2m3c269FNr5BaC7ETXOlZmAsTCzaUtWbbCrKkBMP4yBYInOk
q1QDd0m8pbuTqN1mwiyyCU8/iniL6nJcMjjqEqt20Mm36XWLdMKvjaKRmHI0mIBb7MUclR+t
9wd5+sHz6wN8WAzEuwbN7bzAhyWf+V9acVe/AB+WfI1S6QU84xro46LPKlgdHeDTos+fdxl0
R7jAO6p77fYg1zINWfHEp7/7S0hMKBLawpAW9fXbEs5WJ5JviU3xD9Y7qcsv6Yrnru4IzpvY
OC+yUX+lRlnPGRXO4FyC7skzm/j6DTYfz9i4esviu4oq1riA14b3BBbTbHOxxMbFW5MaW4tS
iRgTsHmPHH9Jsvmd9pANJXKJ2CVCYcQy2uRJS7+bH8X3zbZ+WVELqQt8+FyPH3j6XuCzb/+w
6gNPjl7Qo1e4+l+J/oQv7NlvTzWZgfO2A3z0E0qxxA3UQgO8Q93dTwT7RRoK4ll0QmSIUhGl
YqgB0KaJ4Ho7RPu5yKak+EO5SowFF9C6xhdtyd69HxNZZEPxy5PwoGZx7Y3ao9gWY+D7keDB
5uMpm9wbxTFqJYOtXnaMvHC5HQhe5JKTsmkVLeryW+GIjh2VY38GTCrHS3QiV1WllBYTLx0e
CNalDeuPuPszLP16YVTjvcGHD2+r//jBWNsBPqzxLJUOVkMH+LDOs9QKeHg7wMeVXkcPbwf4
sNLrKUY1QaX3Bm+p4016p2SoiWepCdqlZelVMteGHqhtMaPW21rR5yKbGAju1ekYW0fdv/fM
A0+8XxbJhPeLcrZC+VVe+UO8Xwabj6dssmbqzOFQWEGToU3eL0x/eaM9ZBOTvb4Jpl7M9VHH
4zl21Fgn3i+LdEqqGjEjuRQpuB3mWlXyR+p9q6sfpww+5i/s4SqeJAJnzy7sYX3HLjfAoeUB
Pl7HywUcFh3g85U8dFryjT1ex1MGh1MH+KvreHVIiIfhHN0f6Tmbv3sbXMbbckg7K+MtkYmK
XM7C3f9sMjhi4OvLeEtsKFmJTDwjdVUEbiV80RZDkZm6q0NAPMzm0GZRX82+nUBtCvOOU81y
O7PwuUgmZJoIU/QDiKF9zpvE3bSOt0Qn+hRqiVPaSpHRg9bxlgrGP+LuzzD2a+ipzQAfruO1
5JtasCPvAh/uyMuJDXxlDvBZnRdugmi1doAP67zuj3h0VvICn1V6REkMnFYe4K+u4+mQEw/j
Oao18uuca2MwAmJbPMdk2naJzcvYz99WYXXB/uL6Ywp5S2yikGeUTbS9ciCOFvLu4zkGm4+n
bLLkEmEwTL0pXMjbccg5iWFbZPM29mtdc8kxtXA2nmNWyFuiE4U8zewvI6bYX/yrC3lfYuxX
0Im9LbN620ZDzlv7SUWzOS7wWQVKLohQB/o39vg5sho4SD3AR6/xy6yP4TnlgT5eTS7gPOqF
Pfr5LDYOFSz+DPCGx4rcBry7KmhD4zxJD+iJs7qs9Xdpi8AKcB5kh3+Sv+YmFaAlNiVJWChW
ZWJB/cli0Q79OZsHWWKjKfoFpRFVUzXs2ugeK7yJsd9g8/GMTXj01V6paosAXWyn44u2hIiU
yQjwEpswbskx6SXMqgoPhGyye7k19lukEx59xkWKcRUDR4/4ZwR4n877NmM/1Cb5jT0rA5ST
v/LAD3iBD5cbJVkFrSbe2NNir6cmaN7jQB+W9C1FkQXU9G/wWbnnOl3A1qcLu0FQ8MxwrQ9B
8SQ+oKccPsH+kNduBo409S29XC72JsXGJTau27TWaHzi5iL2ayNN/6fYOHkDL7HRVKhxcRHe
ayHwZtM9DilTa78+9MQTNuHS1zO7cvU/u6Jhi4sDpv/N5t7FeZFNuDhb9916JzUm8Hm/ycWZ
dHKwvESHE2l4YuZerDHYlR+LfsTeHrF33tuvEdiWP8BnFUAlf16Ak0oDfFznxVQlLPQCfFbp
+TY0SQWHJC/w4eYBdf0BOvoP8NmrnCnsNNBWm4HeUdijyXGfDT3xLLGjq2gvrZQIh8D0RCza
ovUmx31LbKIXSkk4Syu9ZnQUeK0X6r+1nk203hIbTVo7xRxNzrmDg+e65dB/7u1nQ048C4Xw
x0lYvbh+bQ08+vBFOw6WeXawvMQmp6oS/s3MrqoIK7rGoh1sbHKuvMSGXicPqqWTSIfT/NYq
AD9S7w+y9qsK2tIN8OHKXk0dzu66wIcVnyVDj8IH+LDia2GXhc4sD/Th6xyN/GhqxwU+rfli
zBf1pxnoLc2E95qvjHiI8iy6o3apNSouhRhsj9xk7icTzbfGpsR8TlNmiiNQRs39tmQezw5z
19j4fotLKcrl5VeIKVjdcjQ9NfcrIx7iEZt4lJDm2qpJkYbGQ2wx93vd2PM77SEbl2+WS+6R
E8OdwROxvCfCeebut0bH9ZtvlfyyFPLnPehOTT8pbTsGR867+xGhQ2gX+HAnF6eG9sMN8OGO
PUnwAekbe/Qavzz7OlilH+Cz36BqauDr+QU9+umEMpwbd2F3iLvJTHAZgRDlWYRCa1x8lyEd
PoI6YO23Rias/UTMBUSm0sDWtli0Q9tNZoLX2MRMsD8auqpxVnRX64s2yIfZTHAZcRAP2eSu
pFLM5O22d87cL0+6BNbYxHhvuNeo/3ScDnhAcsDcb41O1LStdX/Gmz6YsPox99uh7b7N3A98
QF7Yw2e3NfmDDz27fYMPCzxLBe12GuCzEq/m5G9B7Mc8wGe/w0bJXwngd3iBD8s8Dk0Bmr9c
4C1VvPveqTJiIMqz4ATtzaUECfkfDm7ffdGOUIup0lti81J6ylmcVGYDy6yblN5kJHiNDaXO
ro1iSNNVBajCfdEWMTFTeiMG4iGbrEVyd6mXBYwI2mTtl9tf3mgPyYRkq8K9C5mF8TEq9PZM
ZNyf3K7RiWibKo1KN+EGpxmulSR/hN53W/t18LRmgA8X8cQ3qxnUeBf4sMbj1Dt6WnuBj5fx
cgdNVQb4cBlPUq1omN0FPl7KM/Q7HOCvLuaNMIjyMKijF+mZqJI10BNvm8Pf/TDkGhuXa8Jq
NUYh/b+oU9mODrB5NW+JTZj1VX+CdaMoUMJBHVtc5GYab6RBPGTjWihHwIVV1xKwyNth8Tfz
b15j8/ZvjhRhEtdTYGbkAYu/NTpRzYuQZ+YuUhiOrP6x+Nsg8r7L4k8baFE7wIfreZr8xYTW
897gw515OUlGLVYu8PF6XgcdDi7s4WqewGbiF/awznNxmUE1P8BfXcsbWRDlYUyHhsTjOLWt
oL3KLnu/WS1viU2U5Rr7yzfmVR7kdGxxcp7V8pbYUOpEImISfMDqeyzaISUm9n5lREE8ZJOF
VGsvmYuhgZ977P2mxbwlNu9iXmRUZ665gb6Ym4p5M3u/NTrh1Of6zkV45yZgXt4/1d6P/vb2
fo+KKmA5ZcMjcoMq/jbTQUI18QU+q4nJNRpsOXj4BqslMdhOfmHPXl0XDL6LQQsPA332+nJO
GfYZusBHP6HvEJIaOCE/wDsUMd3NvrpOGfkZ5VGqQU/ZsqvHxjWM4LAbt29pL3P1eu84uEgn
1WLUuzXRIuieKu3o0C0vBX6nU5bY1CivORXpRoTm+tY91TWye2/LMgI0HrGxV4BGo0ji8/0K
xsa2DI1PTWjW2PiLxX82JM1FfpzWo6XPLXbkPHEcXKNDyTpHh6nfb2wN9HpNa8Hrf7ok/nc5
DmZUDFzgs1rgdTgM3o5v7GG9F0YQ4MHHAB9WfIVTKWB56Df6/FVGDYfe2KOfT0tJuYJVnAHe
ofdsctI9QjTKo2SDltiVCvlrWCPNDiw6L04j/rcRTZscda/RSbVqjzG6XjMpXMnZUgK9VUi/
Ftlwspxd7HV5xeKibQi2QyH50/2vbrWPZ2zM7zRtxUVfFRd8GBvbcqe53rs7OvhcZOPKjWOQ
X52TEhr8nvf0muaJ59EanRgQ8g2L/0elGTwjtTYx/qP3/gTTQQU7gS7sYQEQrjeoRrnAh4Ue
+1YU9aK7wIcLtxbxZehZ00Cfvc5NU2voR7zAZ0t7KskUzFQc4A1qQmhy2D3yKsqj9I0er6xO
nXOpGR2p71veWKXe9mh+rtJJPZfuOiJiKzJ4dh+Lvrq0t8QmHrE5ZkZrya7ysQ3uttLeXTHs
96328YyNb2uFWEopPXcBz/5001DvJLh4jU30J1b2f3Nh6q73zs4oT/xnluiUsKCoRWrr6tcH
rYnbz+jKLqn3XaaDaAvrhT3c2ChJKppdfIEPKz5LndARyQt8+qi+Je2o4dBAn73OZnFvgR/x
Ap8t7vWexMCGhwHeovgmNnAjtKI8iuBoqTdTyiSi/jJGi3tbPLNrn3iFrNFxNkWLUWYxOEQ8
7TgBKG3i/bvGRhLnFtHFViWDI0ayJdmPpmXkkVnxiIwmUeZiORexDJrIx6IdCqlOxliW2Lh0
a1obUxauQuBxk6/aESgybW9cohNF8fBl70qs/tr80qL4j+D7VsPB6LFFy2YX+Ozrv0jKWcCC
zwU+K/NEUm2gEB3go1e55NJTgys4A324sVb9AQLOKQ3w0U/InRNX8KR+gDcoCZ65/Y68ivIk
RaCl7PJOI0iAXU5gvy1ftMPDZTrFssQmplgoq3BvGbWt3ORHU+/qYL8WuZA/YP0rYhffuWQ4
32HPmMStYv19n308YxMny520Ww8DQrCqx3t8FKfOg0tsoqpn2S8Mu5pyJY66Su+p6pVJAXmJ
TiQnZpesbK13PFr7HznC8q8xHuSOSr03+KzU45aKob5VF/iw1LPEymBF7wIflnq5JepoeupA
n/0WG6Xe0ISOC3xW6mXfR6C5cQO8o12P7g/WaMRU0LOYihbCiM04w7FxseiLpd4am/fAsknX
zK6LYbG3o9pqE7G3xob8tqlV1a9NEwGrrZtGfF+JxPM77eMZm/AmFxcSrXSRCj4j9xiah/r/
qzvtIZuQbc1/L06EqRawv23TwDJN3AfX6JTXqUgpfnGcFDgZt+ro9KP2vtl9sDS0XnaBD1f0
aioER4i8wYdlnm9CFZzIGuDDMo9aqlnhZNs3+rjM44L6+lzgwxU9S77/BWXeBd4h88r9aCSN
xAp6EiPgeyH2vXyrJJKtYMKo7XHsk9tusM9FNv7iMY2J1ZjFRQePYrZsi8y7N4VbY0NRTG+a
i/SIekFlXtsytjqp6dEIrHjEJmp64uox9hOKFsE2jZiw3A9lrLEJwSYuvqlRjvwa2H9wS8GV
70qUvxbpRH3Ost/DZhbBkWhR72cId4PM+y7/wV7AN9gAn1V7EiPrYNLEAB9u08uJDfUbusCH
1R6Hhxz4HrzAZ7/D3lJXsLg8wGe1XtFUMnhKP8BbSnr3Yxk0MivoSZKApt44m5hv5eNoDSzp
belqU5mU9JbYuGwTK66MXB/lnEH/mERbzm9v29p+LbKJAcfSVWvrrRgc1bolR5f6pHg8Mise
seHU40bzV4aQEFgDi0U72My03hIbV22+T29cI7imC9hBmTcJ8duL82uRjm+SWqnCMaFV0Dl8
X/NPlHr8FRaE4Pt2x5v2b231V8CQrgE+XGy01NDTiAE+Lz8Lavj3wp69xk1DT6IDt3vMjh+Z
OYo/1cDI+gE+e4Xzuy0V7b58gbdIz7v6gguCEaVBj/INeuJeq1TyTZqg1WdftMPsTyeuxIt0
kktP1lp7bozO0MaiLdrzbur01yKbOLWvrWXN0nxrgNWA98R3E936i/y+1T6esbGkncz3scqV
0GQ+2zRRMTH7W2PjKrJXEf/lcOMIO0G1544Q5nJr+vlrkQ6nWqlJFjW/18DiTiz6J4rPf5XZ
X+more4FPqsFarTHgLvuN/aw1qsxKQZqvRf2tNajVFDv9d/o83oPNZ4b4KOf0LQmQyMbBnjH
QewkbIxGpAY9yjlorimohf1LJ0WLc21T+2CdVIDW6CRhsyIWMxYwnbTjPKK023mEX4tsNFGu
pWW/e16VIFDv0Z6B4Pu8ExqRGo/YWJJeLZswlcqo19+O5/dc7i2RceGmFmf9xuKcwJb2vKcZ
Uibezmt0OIoO8ZupXVXhOvBaIeVH7v0JXn/Ys/GFPHycrKkWVINe4MMaT5KivjQDfFjHSwz4
ggMYv9GHlXxPKuDh5gAfruqZRFc12oJ5oXfoPJ60D46cCHqUemEpq9KrGtYMLUbbllTZIrcp
fZ+rdCJmU0ozycEJ1Xm6g43Vydt3iU3zr1nUxZE0jlcwOq29Q0u8YvTmt9rHMzaawsOGa+He
q+8s0Crllvzifm8fvsYmp2ocYcwxkKQNPGeKVVvOlCdjIkt0yF+XMYTmN1tTNGElFv0IvU1C
77uc/rKBiu+NPa4FekUHRi7wYc1nqRu4BR/g05ovIu3R8e+BPnud9WUqj4Zpv8GHNZ9fuyJo
t81Ab9F89+kKNLIi6FHyRU+SK1ur1JVBq5FYtKF+5JpvUnJZoxPuHKW3rpYVdIssW7w5Qmfe
v4eXyGhSYquqWlRbxR7NsWiL5Ju0EY6oiKdsqmu+3MyKojnquqWPhPi2Jv65yCbEmwskLpV8
t4TmTG+SfEL3qdlrdCj5jdaKZfZ/BZ0b9UfHj+T7v0dGTnv9Rfsn2gp3gQ8363HKCibjDPBZ
ASCSBD3AfWOPXuOSuSVq6CDGQJ/9DrUlM7BpdICPfkLhOMIEzzkGeEfD3mwueKRE0BPr/pai
0ayb+r/cQOt+X7TFz1knGm+JTTi5+O36yiKIWuVJ+5dmd1XKX4ts/PFFZjmC2lgbYWx80Y7p
Ct+V/NWd9vGUjYXXdiktSmHgAygW7SiEzTpDl9iE/QsTZyWSSG2D54K3eP3RpDV0iU7Utv1V
6Rskv9G0osMia82UPyLvzzD7qx20VR/gwwe5NQaYwHPcF/aw0rNU0GLUAJ/WepETi37EgT6u
9bQXXOsF+KzWI0kd/RIHeIOeYJ3MBY98CHoWqWAlq0RjdqSnoUWjHW67RWcGbEtsXLYR917i
3LMXMFwlFm3p1buP0FpjQ6n7VjDHzExhtGHeF22ZzZjNBY98iEdsOPVX3kVx5cVoHyVvmUCn
MskFXGPjqo26mYVLFsWABqr1tghxnoygL9EpcSTdsr3m0HtDN0lr5ckfrfetVn+UTMBAggE+
XNCTxKir0gAflnm+BxXUEPMCn5Z5nHxDDcu8N/qwzDPfQYCF2wE+XNKzpGjz1AB/dUlvRETQ
s/CO0sKZ1iL4qYEzuJtKenorWj8X2cQpg0uiLMRhXQiX9HawmZb0ltiw77BETFou1EF7at6S
qzJ3+hsBEQ/JOJ5ZYk8hHewW9kU7ZNG0orfEJmpz4sJIS6PWrWN32omK3hKdV4trWFRJ603A
mNbVFtcflfdnOP0ZOAZ/YQ/X81rKjPYPXODDTXph3QfWRAf4sNQT/1vhxOCBPvsttoibQs1M
LvDhip7vdAp4SD/AX1zR4xEQwc/COyx6MIpmq8TgVt4X7aiBVb3vlV9jE3ECzXopPVPODP4O
NyW13UaR/FpkQ6kXyq4oKjWXe+BJiy/64ooej3yIR2w4+Y5Cq5K/NvzKo8p1S31yltS2xuaV
1FbFdxX+ACqgG/omqTdL411jE8G6WiMkhsQaOBrti/6RUu9LnP5Qw4stVhd/Z68/3w3iXn8B
PitBKaea0fmBC3z8UFkF7c67wGevctOesoHnbb/Rh6vKNRGBacYDfPY6Z6n+1EaHwAd6w8Nl
NifCI76CH2UK9BSvndy5NqlosGD3H9cOFTrxgFmkk4R7sVrIuDMd9YB5WQzeaYMlNi72u/Yi
QsrS4SP/HaMIdFs9/X2nfTwjYynqpr7bEfX9AZhVaHv8mUu9q9B9LrLJqVWhLpFk45oanK/M
e/wYy2ROZI3OK1OAxUrlahlMsVk1g/3TVei/yvKPGtgJP8BnxYByTDDheXcBPlx3lHhKo8PB
b/Bh0dcyrkt/ow+Le4tiJ1hnucCHRR/VlAltVRvoHaKP7vrV/FU8ciz4UbhAS71pc52Ua0Mr
KLFoy+BIuaPzuUoncrG0+ZtY/Q0GJj+s5mI9mA5eY6NJX5OnTNIN3GPEmi2i7y/vtI9nZCy5
FM8uXruGzTNq/LdmOfLA+G+NTfg8Nyb/x/9TFLSiPeDzvEaH/Xu2XHN5TY10VPStvWB/RN+f
YPxnCr7ABvisCqiUCCyBX9jjWq8wOu9wgQ8r+uq6ozVQSA304V6CnnzDDH7EC3z2OpdwOUYH
wS/wlvLe5ORvpEbwowwMS/50Fw77sgrasb3W7BB6bXLGvMYmpFGV8N31W7egQm+HNip2m433
a5FNS/4My72LXxkBY5Dblmi8qfEfj8yIR2TCw6+T/69EdQ+0UPJFOwI9qE2qe0tscvKbV6o2
Lp27wQPCa6ey/2P8dz+ftEaHUlX23RHXWmoGO1dj0Y/Q2yT0vsv4r6A/xQE+XN2rqQt4O76x
Z3WA5pTRdOMBPq334sAHNnu+0MevchH0I17gw7U9a5EWg/rqXOivPtAduRH8KAWjRzWscs/m
CgzsXItFW7yr2/345iKdcJez7lvR7AvBqIWyxV0uZOb9i3iJjaZeqyvJViq5vEBbPnf0sUyd
/3gERzxko73n2sSsu4KFS5U7qmHcJ5pviU14+MVpbm2u91yTo85/uiVAuP3lrfaQDqUYrI/h
q9qJ0dSsxcfAj+b7buc/+Ij0hT3c0MWpVfT48QIfbtyTJApWpAb46DV++bt0AlPHfqMPq2WO
zCrUDeYNPvoJRXqqBfwSB3iDkJiNCfNIjeBnqREhkmvzp3vrmbAtVCzawGbmBrPGJoxdLEJo
ardSFO3aKxtmUcsrvuvuzbvEhlPJoiX7vUMqYKNbLNpxSHjbg/j7Tvt4ysZqTKLmbsYG+iHH
oh0i77bz4XORTbjB+M4twuh8V4H2u+Y93tvldrP3a5FOSa00qaStkG+O0B9O+znB3SDyvsv5
T8GT+gt7+AS3phhlAo9w3+DDWi+Ot8BPOMCntV71fRjYlvkbffZbbBxzF6BivsD/xyf8DwAA
AP//7H1BsiU3juSJhgYQIEFeQGaT/xjds5jFdC1m7m8DvBfMhdqC6cHi509JX2al2nik0iPi
BZ0g4L6i9UqiCp7cDPAGPTGdEx5xEfIsYKErixBbdVkBDrPFRTvOcG8na38ssgnDZuauzTQ3
MbDkusflufG9Uccam5x6Ew2XjmzCaI077ehdnc8Jj7SIR2wk+XfEqcTRZ7YCzwnvYCNtMie8
xCbamHspKhIWNwq27fhVe0Y0fvmqPaQTRe3WumZXroIGQn97wvwlnf/C5A0dy7jAh0t6mnpG
Dagv8GGZ53tQQj3rLvBpmRcNuOgJ3UAfLunl0L9oSe8NPizzejIBhegAf3ZJbwRGyMMwj5aZ
oyezdAbPBrc5/01KektsoqRnRN3YGlwT3lPRe5nZ3S29S2T8C5uLkIrFHC44LyNb2Eyd/2TE
RTxk03Nt/j/uLvQ6djK4yfkvl8lMxhIb12v+4SHpEYVTUZfSXRW9mcpbosPJqJn//v0rUPxb
gFb0vjN6N6i8r3P+AxtbBvhwTa8m1NP+BT0rUQolJXgm4w0+LfTCxgC2C7nQh+t5NTVBj5cv
8GGhp4kIfA8H+LPreSMtQp4meeRWc83+/2gy96YkjzJzY1tiExbPxapLvZZ7BY13d1k8zxxX
lthk/7zGql6oCwmhXVNbTjun9bwRFvGITVj4sRYrvboKBxutN/n+iU68fZbYRGWuULX8miVW
cM9He5KG+XY062ORTsRTq5VG7EIPnb5dzbT+aqV3Tsf9n3/917/+37/+63//x//4z//1f//j
6BKFvZCnKzhg7WbD53iDBv8K60OtlgoY0Hlhz+rvTKmhKStv7GEFzik8EUAF/gaffcIWk4Zo
PMgFPnoPK/VEBroIDfDZp+wLur9aqLvlQG/4rHCbVMBGkIc8y77gklvLwtpctqLGF1u8qovc
sfmxyMa3OtlqZyOWQqCPuG5JGuZ2m9f2scimxe7IavP9RKtimAJvW3ZHmeSunPfzTfvjGRtO
xL35hoLCBgd1Wko75jAzlUn35CIb8VctGh2Kb/jA3pq4aIsAvztw+Vhkk9/dDmQx4K1o+MZi
t8NXC/Dfq9T6hZ6HapLUwGOCAT6r9zQSOEG998Ye1nvVNTAYTDjAZ59xywk9CbqwR+9g6cX/
m5hgvrBnn3BuNcEuHj/RO7ReuT9W15Hkoc+yL1yFVhbR3nsBv/Jx0Q6tN5lfWGXTqPrviXIB
l1/ZEkrCrw3ozfK7RqWlzFUyt2KlVXCEyS/aIo0mQk9HjMcjNi+hZ5ms+FPP4Gu2Segx3xf1
V9nk0sT8DyaxAqZQ+kU7Kq1y6030scgmJ+PKViNiRTocz/09JbNL6J09b22NEil4ljnAhxVe
TtLADccbe1jhSSoCZ+m9wUefcZGXvTIooS7w0XtoFEOQ4N9wgA+3yIbtC8N5NRd6R/Mk3Z+p
60jK0Gf5Beoqr9eau69YDT3p3GN60++tSNbYaCqRLNGktF7R4I+4aIfQu+13+Fhk01OWpq71
qPbMYEubX7Qjry2Xe38lHUkZj9iE4Yt19XesqD8b0G2c9hh0zyytV+mY74tIaqvNfB1E6bQ9
Nb376vEanTD7ZCuqJgbboq06hH5Lvd/E6bC1mjSDPZQDfLiHUiMxD+2ifIMPa76eKmjvcGHP
Kj7XwaWB7QwDfPYMV1ypV3Awb4APn+EW820t+JAv8Ba9d58roSMkQ59FF0i30sl/yI0YzCV3
vbclte7WFvDHMpteeiNzmUS5g6YkftGWmWialFuW2EQ4YNhlx1RisYqe4O5IFHS9NynsjZCM
R2xCueUwWegszbdo2M97k97z/+6vXrXHdMxVV+cSmXXUwJ0SLQ6Y/Fm+TtKT1+hwKsK1S3fl
2gU9k/KLvvXev6v3DrschkF1Y7AmNcBnNR5rQktSF/ZwvUeTFTBoYICPPuPcKClW7XhDj94/
IUkM/vUu7NlTZbPY/WK/kAHecWab78MkdCRj6LOcjy5WjKl213aguuNNjjezat4Sm5zIFzWh
StzEBOvPi4s2sLFbV5WPRTYuO3t0snX/xnIHT1lkTygx00TdjWSMR2xcp4lEqYiVhRkckYmr
dtApk3PbVTpNfVvkgsg3FBk8VI+rPrXf8GORTrQOqsavp5F2eLZsrd/wW919vb1heO6CL+0b
elbgiSUS0IBtgA9LvJ4K2DN9YQ8LvJJaRWdZLvBhkUdJBCyRDfBZmVdaQpu/LuwOkTdJj9CR
haHPkj06M3Vfpojr64/HRN6WMehJesQaG9drZK1ko1p6LaBDa6ItvXl5cmS7xEbCJqn7/wqH
TyNakLQthje3I+o/37Q/nrEJuWaWi4SBphJok0yLo7Z/bmezyZHtKh0jYnZOJU6iYV/DHeF0
972GH4t0OGX1rRGRdFIydA56be3/Fnlf6GsYLru+S0DjF97gwyW8kjiDfe8DfLyIlwXMWhrg
sxrPLHpKwHt4gY8X8gj9Gw7w8VKeGXicMcA7WtluG3J87R1hGPosoaDnSlJdEtUiHe0k32E2
x+U2svfHIpucOCIea9EInW3YrzBvifaYl/KW2IRHUmkk1CoTqiN0i2bNWe+HunVkYTxiE5Z+
/oIR+46MSu9wY96WEYw6UXmrdBo131NElV4JDLveVcqzyUHtEh0XbN1cf+daO5x2/V3K++v6
Gmrxrzj4SXlBzwo9pTDaBD/gF/hwPx4l39ijMxhv8OFiXk2GFm4G+OxT7jWxgPnSb+zhUp6l
IuAAxgDvKObdft598R05GPosnKCH2TMVJlMWdPyx7xBGtUyapFbZ1Kh/9a7hlIy6V2/qx5uc
oi2xkejVLS5YWy9+r9ATW9vS4T87sR0xGI/YRDFPpZNrcHJZBPrmbTqxnZkaLtMJ+z/pLDVT
BfNwNpkaur781bv2kA6/6g0vs5uqFZZ5a45qv7vME1jmPekyB/vLd6wT26ZCvsDQT7EPw4U9
XGWM8QlwUGCAj4vPzGCc5Bt79gmHR19Bm0Ev8NE7WKsmX6cw6TDAZ5+x9I4Xan+id8jPiaGf
joAOfRjQYWImXaPUCB7wxUVbGgYnmmCJjabIdi7dl1BmtJAVF21g48v9vSRYYtOTcCssrUlW
0PTAr/l0m5cRz/GIzNvmhWp3JdhzQ8vZe/z8buODfyyz0UxdOHNW7Wjg6JYXLfphf/WiPWST
UyRU12hONetgF1Re7Ez93bXnP8rPj3PHxNQAn5V7JZq5Caw1XuDDcq8ksPX5DT37hJv/SA1s
uxzgs2Iv4kYUDHgZ4MNir2myDN7En+gNguKVbHC3Bo+MDn2WahGDISLKnamAq5ZftKVx8Dbw
68ciG02swv5CSMm+xKPuzVuO+2fuzWtsWupkTTTsIFEDqQPmzToSOh6RCd1GjTTy2Oywpx/J
xDpykY1U13k10p1zhfvsduxKs9zukT4W2eToKzHhatm/VmDZNC/2lXyLvS/39LMe7R2gw8sF
PnyiXJN/UMHhkAt8WOXFoo4Gh1/go0+5iKashrr6vcFH76GVlloH+wYG+PBT5pxgU78LvKOo
1yfOzSMJQp+ldPhC1UxykxapbKjHy46UjqqTM+UlNurKSNtrErjWDM4y6p4T8n7rivKxyKYn
MwmZ17I0Ah1r4qIdrYOTRGQdSRCP2Lw8/cLhpfiGQitYOtrm6TepHy/SaTVbUW7+y9EMJjzH
VTtO/G+rlB+LdCLduL/SxBs5JVSGf9s3b5N6X+bpJ9hH/8Ieruq1hNaYX9DDKqCn1kBHxAE+
q/WUUy1g0/kAn63qWcOTYgb49DF9T9zB4vdP9I6q3sTRr4w4iPIs2cK38c1XrW7hTYZRChvA
HVU9utOuPxbZxNbEBYVIbWRo8OAWy+P3HvRmAV4j0/3j6lcUarlkAVuS+5Yg+KmhXxlpEI/Y
hGwLmadRP5YK5m8fMHBepWMxWFXJv4/dty2wod+WaeDbcvjHIh3XbeTP3NhfNt9aoAfsa82q
32Lvqw39CprSdYEP9+lJygJ+vQf4rAAIlz4Dj5YH+OhTDp8+AQ8bLuzROyi5JKrguegAH/0b
lu6bGwLbfgd4R0FvYutXRhBEeWbO32MQ2D/wUZWAE++3CNY6seFYY5NdrhWpalJiawJOGW3x
rOJm9we3a2w0MfeY0m5UxUALrrRjzzidESkjBeIRmZerH8fBrbIaGO2+aUTEb9+vXrTHbEyU
skQtnCIbGVV4W+jcnkN/LNLhJFpNRdm3ewL6qfpF334vGxTeV5n69dd7BNr6Bfjw2W1JOYPt
KgN8WOj1l9M57uwnO9IvHlr71Ypa51zgw1KPUkQ2gVLvDT4s9SQVsL5yYbec3N5b+5WRAFGe
ufJ3jkEMM+6GGmZusvbTyTjGGpv86tDLmmuuHRd6Wzr0ZqYva2wiNqSXlkU7a4PrrH1HuUhu
66w/37Q/nrEJ0ValUNhRd39A8MntjtrkLJ1jlY69BmWIfQ1UAYN3d6VzTPyb1+i4ass5NxFS
KQx6hfPi7M+31PtSaz/1zzfYnzfAh4t5vl1t4Ds4wMeLeaDFeSDPqrtXSyU6snyBD6s7f6kU
NJcc4OOFvELgN32AP7uQNzIgyuN8juaLbqSWFdwfZUshb3aCtsQmanLczLd0Fv9G5wY/v5C3
xMY/XBFo4b8/i3+jpn68JdDidp7k55v2xzM2Yc/XtGs2o+bvG3xYu4NOngT9rdIxISlVuvjP
Eu3SPVHKW6ITpTwyl91S/Q8Hs+Tiom999+/ru68x9ctJM2zr9wYfLuVZYgL/hgN8umkrNbCI
f2EPF/I0WUOjii/wWanHJfUKNjcO8HGp1zo4lTbAO9ryJsZ+ZSRBlGfu/K1Zka5RZmngeKpf
tKUtbxLFtsbmFcXGLl2J1AwcKdkVxWb3ZmtrbCI2uLrosixF0PHzPbHBc6k3ciAesQmp53uy
YpmalgZGqGw7tb0ft12m01skfEeDgLgYR6XeDtvFaSlviY6rtgjYLU5Fe4eHMP6epbxPMfZj
9Jxkiy3DtuGQ89Z+WkHPsgE+K0Az+QYHjG4Y4ONnyaro0MAFPvuUraZwQ4Xt/QJ89B5W171i
YD10gA8/ZWopM9i9+hO9o944sfcrI6iiPAkPkOR/Zggoy1UZHArzi3bItsp3bH4sstGIXZQw
4ZYWLYRghW7Ls+m3kbMfi2x6mBX6R7b1RhU0kep7LORmji9lpFQ8IvOy9ytW/ZvSI+nlpOML
86TauMgm4u6IqZBTAg1x46Idz6b/8kV7yEb82WTN+kq9y6BJhCym1fzuCvQfZO+XU/cvDCgF
3uCzgq+Gtxh4rvzGHq43amqGJsZd4LPPuGXf9qL5Uxf4rNyL6V4GQ3cH+LTc6wlesS7wjorj
xN6vjLiK8iyugtlvoeZq0dSFVrV2/KqmXs5rbFz5N3IuUql0QU3p044GaG63wSgfi2z8renW
JI4SSziCg2pvR/7dXO2NsIpHbF7+flVbbC5U4UmETzdzXmWjolr8AZWo1KFNGbolF4XutOvH
Iptwce255AgGxntu+9LP5lvs/Q72fr2CVq4DfFbllZy4o+2DF/i4zmNGE1Yv8NGnHI59vmiA
li8X+Og9NH+1UNvaC3v4GbPFMRnq63Ohd+g8ulNGvvqOXIjyLLMjxgBzby1rbYR94v2iHZkd
9bbt7scim5KoVKtWspXeQEO8mCbfofPqfVrrGpuemvomSyOBVtAhEb9oQ0vk1N6vjGCIR2xe
9n65aw7D65hIOun4ImUi9BbptFZq0XA/ZmVQHNGWnoypvd8anXDqizplL61yVVS3ftv7bZN6
X2XvZx2sVwzw4bpexUMdBviwGugxRwN7/PUdTd4PLf60g20NA3xW73GITExNXdjTeq8lzugh
7kBv0XsTg78RDVGexXaIf+CNI/mJKuhns8ngb3qIu8RGQ72Kf5TEFB6B0T3qderwt8Sm+09P
VJv428O9Y5+UuGiH3ps5/I1siEdsQrlRzZRr8adTwS3xCYe/RTq+Oyqdu0tJdW2FDo20HXSm
Dn9LdMLOmV/zL67K0XeNF0ecv/XeFzv8dYWHgt/gsxqPIxwdjWa7wIfP9TQZOsY3wEef8su1
D1zOL+zROyjimwcBW/UG+OjfsPTIOwUnbgZ4R6PebDB4xEKUZ1b9XapxqVECa4R+2/cMBufJ
wrvEJvuNrpwj9K1VATuO/KINu6z5YPASm8iMI4rm/ZLbg8HgHU4pQpMugREK8YhNzH1kF0NE
OdQ9+KrtmhaZabxFOlYpuxbOvfruCPQ9jqu20JnsJ5bohF2fUKEsQmagK8+3x99f2+Ovok5f
A3z4ALcmEjQo8AIflno9lYomd13gw1KvJMugk+MAHxZ7rtHB1uAX9GwbIeVUGpgeN8A7hN7E
4a+OSIj6zKY/HP5yWAYraUVbp7Y4/FW9X33X2OTkCqUUFpOIAEPHgvMOoTdz+Ftjo4lya9qr
hQQXbPH1i/bM0d5vKeoIhHjE5uXw1+JknZoVxoXeDt1K9f7wdpWOxSi9+earWFMwBzCu+mSh
t0YnzFyEa42TW+lgQ+i3A8xf1OHPvyiYOhngw8U8TU3AMYIBPl7MkwweKQ/wWYVnlmoT1Ofv
DT5fziM0sOMCHy/nFbDeeGG3aLx7Q446IiHqw7iOrETVhVEr4ARWXLOlP+9+FnKNTJTlcg+T
Mu241fvn1/LW2GjiomxVOpHLVjRfjrf05+l9f14diRCP2ITzi2rlVyhEZYadX/YMYkx2E4t0
rBi3yllL5dJROp9ey1ujE2qt5Z5bLt0UjRT9ruVtkXhfZvIHFiku7PFKniqq8y7w4bYtivoI
WMm7wIcreS7QO+hFPMBndV7uKaNhRwN8uJonydCK8gBvkBN6a0vrC/DIhKjPfPpbq3Eq2Atb
Bq3KNpn8absfuV1jkxM3ruSLVW+dQcvCuOizq3lLbDSRa3BfglnMtzJwNW/HyO3M5K+ORIhH
bF4mf9wiBlBiVBVTE5uObUXup35W6VjM+5iwuUBCvd0P+Dmv0XHVJjF3X6yXMN1Gpd4Sm99d
6uXPMPkDm+EOt8Ghw+I7zqI2yOIvMx5EbV4G+KwszpQauD5c2MOimF2jwT40b/DRZ9zFNVoB
J9AG+KzkZEoFHJq6sIcL3MVSJjS2faB3lD/L/XxyHUEa9Um4QU1sWmuYg0g37HcV12wgU+R+
XGWNTBzvmoviVqv6lhi1odmxK+Wu9yMEa2x6nAlzjmNuJmHsbeubQt9uVdfPF+2PZ2w49W7G
pZC/a2gj9R6Bf+8T/WOZjFD1F0191xJDHqiE3DGrkm9NvD8W2YQXlTkdKb4gZXAruepF9bsL
4n+W5yDqRjPAZ7WeShzOoSknb/BhtVeTCnrUfYEPqz1frdHJzQE+fJDcUjPwrHKAzz5laezL
KmraMNAbRMXrCPduGR5pGvVJwkFJvamwkEiNJQx0cNnhocQlT9bhJTbi+7uWC0vtrWdQvvpF
O867+60W/1hk4692mA6qRKJdBkvubQsbF3yT8+6RpfGIDYe3nUSPpj8iI7h5dsOblpnvCtQ/
ltnkWl1JZs5MhVE2eUug9K1f58ciG1/MnUimzj33nGHjwW/Ft0nxnTceLGCh+8IeFno5ofMW
L+hhkSepoHGAA3z0+TLlmozRuL2BPnoXjUoqhn1pLuzhpxyGm2jL5U/0DpF3GwDnS+9Iq6hP
QgRqqi6Ss/o/RYwwSn7RlpPuSZzdGhtNpZfapfTufzpc1asbSkcu8ibFliU2TCl38i8s+dpb
0BpyXLSjEtYmI1Ijr+IZnRQ2kxL1bdOXARGki3YUkOdNjUtswoTGZZHlVriUDH4M4qotD+fe
dHD14UQ4trUe3oMFDILkRTbfMu83Mh2sbNi7O8CHexs1KYF/wwE+rAZ6sgp2ugzwYc0nnAhc
2wf47DGulNQKaDs0wIefctYE+1D8RO84yNXJBOkIrahPogRqcq2XqRR1wfdqN4Q0n25Q2fOT
3CU2EsWjVsOIimIlBgt7W8qUr/aSu3V4iY3vqKWLSLHmjGCj6R0TUznftgP+fNP+eMYmJJ8L
JP+xRi4zbHuyo6/KyUx2F0tsKLbCMW3vq2DpFWNDi8bM/63oOlF8i8/G4ni9S5ZXvN+3zfQx
xfcFtoMtg10hA3xW5bF/kMGy2YU93MalCT13vLBnn3AuyVcN8ID+Ah+9g0KSWgdbCAb4cCth
SzWD7UYDvKOmJ5NGvRFWUZ8ECLwyH0tTKaLdwJajvMl00Car7iIb6l3jKNpFXgHfoLwlYo3t
NnrjY5GNpmzS2PWQ9NIVzTrecjjIE9PBOqIqHrGh1GsM9vqmu5MxaHcSV+2gcxvd/GOZTm01
Wy3MOTfQxIm2FMMn+Xcfi2w4STei3lx4W4UFnn6X9DYIvK/yHMxoNsIAn9V5YlEWAb/hF/iw
0gv/EbD8/caefcZCiTJY5Rjgw0rPN4mgK9mFPdxE6MtpQUNYLvBn67wRUlGfBAf4Rs2KKrew
yc1gfdcv2sGm2mTxXWRDbNIz1XDJreiU8o7w2fmU8hKbqEpKjI02LmqgzouLdlS+aHJ0OyIq
HrFxxVa6dOXIoO4KWrJu0nlZJ1PKi3SqCZM6pYgGzrCF4paj6FmfwBIdDls0a62HJC5gPf/v
OqX8t/ccbGio/QAfruSVmAsA16ILfLyWpwIqqAE+XM0TX9nBE+UBPl/NQw9DB/hwNa8nKmDN
e4A/W+WNmIr6LHSjixr7ShUTQWBPW1y047RWJ3a/i2yYpClbztYF9dU8UM1bYuObg1ZdthYp
rXOBq3k7CkZTlTdCKh6xCZUXESIqOUvLcExc3+GiyHXicLlIpzZxReS/yZhUg0Xrjm9pJqFf
vWsP6UQ5j01blPIMbIjixbTIb5H3e7gOciew0nOBz2o9pWRgXuGFPdyzFTtQNA74hT2s83pS
dBRjgM8+4W6pEqrmL/DZal6TZAQmnAzwBi2ht91F/7PbSKmwZ5kbTf1nnKO01lzxodW8Lae2
eu85uMYmRjpZqfk/2W856Py5pf7lOu9+7V1jExuYsP1WqjWGodHh4c+u5tnIqHjExr906t+6
aDPkJi/76nM6T/iXr9pjOjWqrNxYmJqBXTB+1RZ7abvfU6zR4Rj6aRofAukKC721PcXvLvTk
MzwH0R6fHV/WbfMh5939pKENZRf4cKGxR3IQeJR8gY/Lz4y2cA/w0accJi7ZQHk3wGfLeFUj
BBss413gw09Zw9sfNO79id7waeEyEQYjRcOeJBv4A3ZJUCXsiNlAF4C6J/at3DpX/Fhkoyms
e80VqIiigyFR7t/AZjYMvMYm5norS4tWLieDzu+nHeHnU48/GyEaj+iEX59kaZSb/xstImwy
+btttfuxyIb9VcthFp+1toIewO6wzsh6uz34WCQjriXN96K1kVVDOxfku21wl9L7Gou/eOyg
Pd0AnxV8UeJkMEZsgA9LgZK0wSknb/BZwafhrYr6w17gs4IvpmcETQS+wIefMluK0hbq2/1G
7zhbnmTJ2sjSsCf5BjVRaaU1i3R68MX1a3b4FZZ8PyiyRkb9PlcrXGPmlNBckB0RcNzypOK4
RKZHZprVLF3C/gWTFH1PZNpU7Y0cjUds4kMSSo+bxAsHV4P3DFbcW0muspGas4TZXm2M2kCl
Heb9LvfuoxPX2PhSTkVb9tetUwXD+fyipb73b733Wxj8GXisPMCHj5XDWhhs1xjg0zWfhPaT
XNijz5h9a51iMA91fHmjj95DKy1VBWuPA3z2KVe1RB0s7F3gHTJvYvJnIx7CniV3uC6qteRs
bBkcv6pbGqH8vtx376+x0dRJC4uF/QqBPnJx0Q6hN0lUWGPD5G92Y2pKjBuHx5nnDm00Mfmz
ERDxjE6ExBC5QGJhBTvVt5n8TUrIS2wotZpLFqFeGzFIJ67acrT8y3ft8cNpliuT6z3xPQVs
8rf0cL6l3m9k8sfg8ceFPVzYC2N60MN+gA/rvXDwhY/43uDTiq8lQy10fqLPlvYs/qPoWe4F
Pqz4RBIVtII70DvOcicmfzYSIuyJb39NGtkQRSSO1ypYUE1lh0oqdFcO+7HIRlNW7bEQl0hk
RucstqS1zY5yl8jEqWzktbTsy3ADV2FarLg8UXwjIOIZmxTDPMVfsuLaAjRNOWDrvMaGwp6V
yHftYkUymHrjV+2gkydj6KsPJzJVSmlF2Bjdyy42FX8rvi82+avwuMgFPtyxF8slONY6wGfX
/9fENLhWDvDZp5xraqh5yQAfvYeSSzimoLHeb/DhI+Yw2UVHgy/wjrreZDTYRkCEPTHtD88+
M1XqEd7BaBPVjj5+X+gnS+8im6zVlbBari2DNhZ+0Z4D3Mmx2hIbTerrrss8omhCxNj4RTuO
PGdGfzbiIR6xieE4zf58XE24QAI/kZsMYKhOSsiLdCxm6k19D2dNcJW3JT+P7yadPxbpcFL/
OToTZiJc5el3XW+Dyvsqp78IsoSd/gJ8+BDXV3bwE/6CHhZ6ca4NSoABPvuEhVNHJ28H+LDQ
e00ygDrvhT0s8ySheesX9rNF3kiEsCc+/WHYZ1X9s86+3WDU/7jtSGgrPCnkLbJh10UsufUc
Phao/8sOkTfzf1ljo0nIxZZ1l6zSQR85XeyVfyLyRiLEIzYvB4R4MMKiKoQlMG4SebO4jlU6
FrsU/12XSrXBdLbkdczsnNfouF5zzer/ZNZc0DCCxXGmb5H3xS5/Bp4LXNjDhTxNmdAD2wt8
vJAnaNzQG3u4jKe+QIPbzgE+XsbjDvqqDPDxMl6voHvOAH+2whuZEPY0r0O6b9275t4U9cTb
k9cxO0FbZJNLGK6FLjIFh4hPlPGW2GgqJGLacwsdgZ487zhGnzu/jEiIR2zCw6Xklo0z10hk
O+rjLPcOf6t0zNWdmPXSSQnscTpRxluiE2U8jmBG9neug2EqcdG3wvv3Fd5XWfwJgR1RA3y4
jGeJ0R/WAB/uzaPUBPySDfDxUp6icv6NPSv1XKF3NDf1jT0s9FoiAlNq39jPlnkjEsIexnVE
HcK6aRzWYuWIvKWXnF+pAHdr7yIbao2pU2dtcB2PdlQlp3W8JTJhyRyztmZEmUF/v011vKnK
G3kQj9iEypMeQ9AccyXlqL8f3U7I/FimU191SVXmLgZu613lfa5XzMcinSjJ5dqouQCvqFvh
37WO9yn+fvBI9pZcp23DIecd/ipaRh7gs9ozUxLUt2uAjx8jV9SdboCPPuUw7Wuoj+MAn1V3
TVOpYL/gAB/eYWhNFa13/0Rv+LRMHf5GYIU9CRGoKfvfzX8nFCkCmAStWzzkuPKdavuxSMbf
BYuOQbZaTTO4w0o7+hC45clUyBIb9g+YlOxKvWspqL2QX7ThTZtbvoy4ikd0XgZ/4vsxK/6A
QNG2yeDvvjT3Y5FNVNmkcddamxiaD7pYmnvi8LfEJtz6LE7F1QrqVxYNMn9HBfqPcviTBnpf
D/BZwVclMaHpwBf4tBRIrYIuiQN8VvDFZA+4eFzYs3LPeoqqBDgE/AYffsbSce/zn+gtcu++
5NhGbkV7kiVQU5QZ4mheLBew5Fj3VOlmhs5rbNRvdGHnUomlGmr8shaB9d+MX+7rQGtseupK
nKVUV+OopOhbTv2ncq+N1IpHbF5WoZlcekW/HajFtzn83fs5r7JRUZdGuWfO2K9mtUL350Py
21mXj0UuknLhVpxPxEeBB2Wy2I/xrfZ+B38/Q8NjB/iszCs5+XcClHkX+LjMYzDd9sIefcYv
xz5Bz6l+oo/eQ/NXS9BgtgE++5RrLalldNx7oHecLU8c/tpIh2jPkjsifUBz7tIy2g1RtxyR
8Ssj4G75XWJTEhXNLiBFW+0gm7hoA5te7g+X19gwpUa+ma5GjQ1s73xdtEMbTfxe2oiHeEYn
sYmYNRfjvns86vciZaL0ltj4bW7Fem+9OakGynDaMl41dfhbfTiti9ZCYS1EuMPf3zI87h/l
8BcNErDFX4APl/ZK6g08lx/gw5qv+88Arey9sKc1n/9HGdyMXuCzio+j7x1crQf4tOLLqXfw
Hl7gHYW9ibtfG/EQ7VlwRyEhI9PSmzasFLbJ3W92kLvGRlPEZomRdpdIaF1vzb7iz3LvNvn4
Y5GMKzcl0ghTiLg2sIs/LvpsuTfiIZ7RCbnHxvldQTps6Hw/nLTGJlS1P5bSq/YiDWx/8qu2
eC/O5N7iw2lWsyn5vzuh5uFprVzxLfe+2N4PTWq9sGcFHksMY6EzwW/w4WY9jdkPtFnvDT77
jLMlApuyLuzROygiYamAHSC8sWfPlgsn6WBi+gDvKOdNRkXaCIVoT4z6Y7jXv+xFetHwPT5p
7FcmzVOrbISUa9YmNVQEyGbHdMV0IniNTXj0WeXSokmPC/hz3TMRPPN8aSMS4hGbl7GfdjZy
PeSLBmZhs2ki+HX35q/aYzpW/CVzMWQh7Qmls+NLOp0IXqMTHn1MTsSlcOcKTwR/G/tt0Hdf
ZexXCfX3vcCHT29rIkWnMi7wYaHX47bgQxk7fLAfzQPnlOGp7wt8XOg1dDRtgM9LvZJB85cL
/NlSb4RBtCcO/WHv1ylrjlnailpm7rH3qzqpryyyycKmufXw5UBbef2iHVLP7kN419iovzbS
SSjn2ioYpxgXfbbUG1kQj9i87P18O5GtxjMCk163eThPTm4X6YS7UOFcuXNj3MN5SwMl3ynX
j0U6rtpKZM28dF5Hh838om+p929LvdP2fiURHGJ0gQ8X8zQ11OxqgI8X80TBUs8AHy7mRUMS
6Aj7xh7WeJwKuEBf2OMKrwoo4wf4sxXeSIJoT1M6tPpmjXo2NGtgl73f7Zjqj2U2uRuTVslE
qCY6UcxbYqOpsApV9T9b0e6KuGhHM9vE+KWNHIhHbF72fixNXOB1FrA2eULhLdIxLdR77lRe
svW3KeYt0YlxYN8ZURcXq0qfO0P8rfB+B3s/Tp3RSLYLfLyYpxUs9Azw4bY8/zwRaA8ywIfL
ea49GuoZdoHPSr3ckyp6cHuBD4u9qHKCZe8B/myxNxIh2sO0jkq1qmVfgdFEiE0mfzox+Vtl
w03Yly0pWQlsMI6LdnTm1Uk5b4lN+Lz7iyOukHwBRptp0o4v3lzsjTyIR2zeXs5SpISoKPXo
ye1rsGv+qj2mY7n1bq72soQP8lkv50k5b4mO6zaVzJKtlGLgLycu+juKvfyXd/l71GQOtpdv
+EZukMZf5T2oaLb2AJ8Vxjl6fkHZOcCHhXE0WYMFvAE++pSzlggeBJXxT/RZ4ck9xcAcJjwv
8NnnLKa+LPz5Qf9/AAAA///sfU2OJTmO9IlGEEVSEi+Qi4hTDPBtvxlg7r8Y8j13b2AKrjRX
KpRZXdENNHphXhV8cpdM/DG7W+gTvYIc3855OGU5zTT6I4ODkBIk9oOR1Qz0DqRF+oNa7r3s
5sKRRJECbc2aOm9B+SQtSYXqIBU6FY2lbKStVqeVnUBFb1uiFeS7++AednppPIomfMVNcnN+
DDvi6pIXrWQd5NyngiG/g9TStfmnw2jh3h9aQY3ZBkMrU9FEaSNLtxIi+ArKbMzWQ/50avyP
kh8UBSu2J3gv5xP24x1lKy/sZsYXg9uofsQB3sz4OOw30DHvE72Z8dUkGbx7nOCtf6FFjhic
Gz2wK5KHPJhRPk01+iOjA03qJM+ol9YqYwkdf6iu4Ec6MBubC4fDpS+Ha3G1ToIdwrymjN/q
ID81FY0mqzmzOt0T3yuwSrEusvrNd9z1etV+PI2GxDyYHP64Cioa6xJX6ZLbYBx+KhoKV2kj
Cas+p+Qw3VsyQN7utoHP6Wistu5LEzPxDbxX+EPfMyyL6N5+/UElcD7kBG/meSUJbEx6gDcz
PY5+O1SM5g3ey/TUzLdPUE38Qm/9FVtxAgKqBB/YzZk9bakz2NZ0oVdwvdtUmB/Ap3lFf+SP
UJMV1uzvYXFagZZA/KEVXK8PTuCpcCQ1v51obaa1VNBALR5akdmjQWZvKpqeusR0UW7klxmw
2yceWsL17nj49ar9eBZNedW9o9mhWMmor8iaqvdtu8jHZDA59RLj5EFcOWdQmiqeWhFOGUhd
ToVDSf1SL61ZUSJUrMwf+uZ6i7je75If1AL2OZ7gzX2OL+8AlK28wZspnyW4hnSCN1O+Rqmg
zP5C703u1R7WRmBy7wDvXWcnR6k1cG7iQi/pdbzPutjpYGGPXBLCKSRb9Dj524ju9qvsRW7n
Yz8mwwkdd/+RelTaChu2WciaZsfW70nfXDQ1SXc23lX9/Slg9tUfWlLO5fv7hZ0mFo+icQLn
1wrRkAOvsHW2LdHcGYjUzAXzEqnxA8acT2YCB0EWjbXcC0R+TkZDiapJ3P58iTKqoDspEPnN
+X63BqGAl+E3di/LI0kZbBw+sHvP/hAVJLA6cYK3rrCVluDWnzd26y/odA2XmD7BW/9C7ezv
FUiST/ACAkFybylip22FPbMUkRzFTj8AqXfDXoq6RMbY7zcDcjcVTUlOgKWJ0yGn/OCZGw8t
IXf3NbW5aHzvKjVrt0xdKija5w8tmZW4zRpdb9qPp2uTTYidq/p/CZZAWtJ5WG71vz8mo8nJ
6ZCWRv62sYJGXPHQl7Yefk5GQ4mp9hxyQRw5SrQWPfXdfLO7P0OBUAWcfDjBe2keO/EQUMj5
BG8mepZqQ+XYD/Beokf+s3TwLzzBm6mev1oE9oue4K1/Yaj2GDzFdIBXUL2BTbCdlhX2zE3E
T91oL69aRBi7oPhDK1T79DZX9DEZjTODSsVP3l5rxqneiskjehlv3h3Ak9F00apZrHVisCfE
H1qigXLbdni9aT8er42fGVRKL85DBB2PX3EN9mh++qY9jMZZW38lV/0lbtrBYvQirnc/Uf45
HY6J+XdTnRQ7Ea+wQOS3BuGvk73dGoTipKOANY4DvDmZp4lQS5sTvD2dxwUt2R7gvSyPI1EA
cvkTvJflEePCLyd4c0Kvp6boBOEBXpLQu5/HsNO4wp6YCdQwE2jaWth4KTh9W9fYrCnd64XM
RVMStUwqtVNmQfeJJb5k1G/VTz4no/FPr5nU3KrTb/hOkfKCb6Fku2/Rs9O24unahANeqf66
mYATa2XJYHQhGqSOp6LJqWVfFafgJM5bwdx+XmKuPc7oTYUTyTnJxSir7wfg6fWd0FvC8X6X
CmEDq6IHdi/Rk5x6A2t6J3hzbx6FBjestJJXHDKPaF5J0hX7lE/wZpoXpVg0mXeA9ybz3uV2
NO39Bn91Mu80rbAnRgLVOY6EM3DnUllQmreEGKkMDt+paIIVFKlslTKhvVJrqAS123b/z+lo
TFT8HpMtR88k2se2JJk3qtuelhUPo8lOV0NlgPy3MjiZt2IUo/RBMm8qmiBspVsjY21+zURH
MZbQvHu3l8/pcKwHv6sUcj7o1E889e9I9PgrFAjB6ccVY49/a6U/VF/tBG/OM1pqDGZCT/Bm
+pkTKmF1YLeucZFeUmVQT/dCb/0Nq79aSqDd+wneu8pV/GgsoMXnAV6wschAAttOTw175HMQ
A17WGvdu8mAsZIUBDqkN+rmmwgk9RZFsvUSmjNFZ4BXSS2S3nhqfs4vjJzyXXtWYKmo2/npo
SclyUE8+PTUehaOJiUrcEFSlgJ3L8dCK1BwPLjtT0VAKKW/uRs0JISgB5Q+taeu8ywJ/TkbD
vonGKJU5u3Vijb1qPOmt86cT0H+Uzh+DfaIHdi/f01cPCjrF+gZv5nuapBOq8/cG72Z8FKZm
MON7o/cyPrFU0B7ME7x7nSWB8qcHdgGlKHZvRGGnrYY9sjoIWbhi1UqWzGD3IK3RkiMtg+nM
qXAkUdNuvSuLga4ai6aA+4juza1NTjlnKf719dxAz/HXQ0sa7gZXi9NV41E4moowZbWquTI4
ihgPLaF7g4zjVDTkh1+MOpl24g4awsZDC6KRUffgVDScSswi+W6fOws4ox0PfdO9NXRvs85f
j+5X7As8sJvLyjWRgafRCd58/ktqMM17YfeyvCoxzgmO4x3grb9gq/I63jCJvwO8d41bK6mC
RPkEL8nq3bUN+dF72kPYIw+ClvzgdR7K1H2fB19bf2hBqoWq3MmjfEyGI8nYr001Iso1ozRv
iZqzjdoH5xaHQi5fW9insRGoGDzrLfuXrN6gU/V0iHgUDvuHKlaaqcXMC9g2soa0jjT+5qLJ
qdemTh+1laoM2ndEn9MKDn67EXxOhlNSJl+a2vyKVA2t+vhD3zxvEc/7XRp/RmCZ9ARvTuz1
1FXBRvADvJnwWbIC/oYneDflK0kbmh090XsTe70l2L/jjd1M+XLoCqKWnyd6SWpv0Mh/ukTY
I+3+KOUK5WJsVkAd5NdDK1J7eZBwmQpHUnFKwaxhSIJKlckSYwV6pRLvDuK5xYlLdaHcuRRl
lJHHQ0tI30/ftR/PwinJ2atGPE5gW0M7PVc0kjjpG4wnTUWTU2tSyelezdU5HyoDs0JQa2ji
MRcO+VlUfYMJSu7/dLQyPdc18E36frPIn0lFG+Hf4M0de37VA68dL+je4z9mAxg1gT7AW1fY
uKVawMLjCd76G3J5KZJgv+EJ3ktCW0/VQDWOE7yARQyngk9zCHsi2R8DvmxO8uI6X0C5skVT
wXV07E5FU1LRIA+5FBYFe47ioRUMb1RSm4pGnKvV3HOkKrl1jBLJIim50WXiNId4uDYUUnK5
ioeEztOtkWAs+ZZ9f0xG41SN/Xux7I+JLxBGv/2pJbXogXPHXDiU1K8RhVVLyVpRFee5nt1v
gvdn6PzVDGZ6TvDmCq4mBt/EA7uZ6Vmq6FjwG7uZ51liA01PTvBmnpf9VwF79E7wXp4X8zRg
Z86BXcHy9LZHj3I+7CBe/+8Jzyut19qUKUdOAuR5K9R2/OW/ralNx+PEQIpTrkLZIwL9LeKh
FX167S4z+TkdjyQOUR5tmYspOJjhD33xaPAVz4/H6+MMMkvW7j+XgrnWRaLOdGsw/DEdT47+
m+rXYSd8CvcexlMrAqJb/+fpgCiJ81b/fsQXyAgeNvkW+/t1xrdf7K8RmKw4wZtTepL8TQRz
ei/s9qRe6WCvwwn+Jnv/h+y1VBuYWD7BmyvLOXEHyd4b+7UpPd/R6SITz7w7lLK02p00SwGL
T3Vy9O4vvXp3iaOP6XiKk9ds2nslP3zhnqOyIkn5KkXenr1z8cQWGxZgpbdg4zv9hUeJvSue
H4/Xh6hwNFOKdAEbcsuS3tBIWf30fXsazyu5F+554dLWK9hF/vXJvemAKEbyjatQzH6jLh7f
2b0VXO93if51tCfkBG/O7rWUO6oNeoA3t+tFDy5YhTzBe0mfaAIVQ97QvYSPLKGJpgO7l+6J
n0AGizi9wV+e3SsXoXjm4FFqdLWVLq+DC83urSBIcmtv9jEdT3CDzsRUosSGev0ssmuz0fk7
F4/fCLVKdoYU5nOozGRacQ3/SXavXHzioY9HyHrU1s35JKy+vSS7x32UTZ6LJ2T8Gks3YSLO
4KD0ouzevZDM53RAISXjgRRjf+PgiaA0V+L70xnfl6j/Eer8sKSEsmx6ZL/+n39TuP5fgPfy
0JITK9i+cYL315kVlJ0/wVtXuUjX1GFLvhO9ObmnSSr4Jp7gvetcraWGqn4d4AVbyyvxfssP
+OI7j0wGaqphyJO19UZov3g8tCAgldvBkemAJGnPpWvv3KmDHrXx0IrGwnorzTa/QJRYpIWn
a1ZFM0Lx0AoGd68DeAX042FAIernl4VmTahJ3aoESDRKec/FE8PZ0qX4KpWQckcJ3JIbg476
G+bi4Wgj97tI9/3ABOOj/sx3BnIV7/ttYoAZnMk9wXvpX+WXJSU48PoGb05DSvJLNqoT9wbv
pn+WFJ1xu9Cb6Z+fXR075g7sZvKnPVFHpzhP9Ar6x3fNUnEYy8UunpgPOJPLzf/JmnPRil6U
46EV9G/YbTgXkCS2rs3868+VwaS2JFkyOayjfOTkAr1MzUoOGWhRtIl5ldnFvS7gFdCPhwFp
KjXnbNR6vHPYZ6SLEqy33Xkf0/GEqrPVot0sxnlh+reCnpfb9fmcjoeTZpb4NqWZgqpn8dA3
/1vD/zarA7ZIQxkoF3OA9xI/jWZw0JLsBG8nfrmDf+EJ3kv8qv8uHfVOOcBbf8PWi+/xYE/f
Cd67yt2PVS5gYvJCr6jb8qguqBeveORg0JIf784p2LlfA80y4qEVhdvaRm3/cwGpc9LaqhV6
5f6wVdIlogNkddT1P7lAlJr4xSGUPFoFPSPjoRVzJi/JnZ+8cT8eBuQ3clJ/00w1BjRgrcAV
rZSstw4g0/Hk1LuVrsy55C6gTIM/tWRwZth6OBdQSWF12MMlsAuaC5p1Cfxmfn+QXmBlsBP4
BG/O/GkyA6nBCd5MAM03A7A088bupn/+qxCsFnig9xJA6qkWsM30BO9d5VZr6gROSF7oLy/8
1otfPPI0iBouVcpmWRk8jlcVfivdHV8f0wFJEnNaEQo5YUqNzuXKisq81Vsdt/kFIj+Pc8vM
ftXJoGPa66Elhd8RAawXv3gSUEnB/Uj8eh4GKpvFom8FjKbjyWEtrkTOmbg1BnOz8dQKAngv
Fz0dEPkCleZc2ZyoC2o5mOZ6W74J4G/VDozbGOr2e4D3kj7i1BgdNH5hN/f6hSAgSJtP8NY1
jtnhVsDEwQne+hv6zTkR2pN+gvcWo63HoQX2Ih7gBXxiPGrcLj7xxA6gJuldtHZh9n8+Onmy
hB9VGRXe5uKJqWHToho5v6aoDPGSJm8bFt7m4vEtosTdWkopTcHu0thXluT7RqPG7WITz9aH
CpXcijn7MnAfWqYiOMr3zcUTQ8PqaxODW40UF4pewcclj/J9cwFR0uZUvFKjYopaH012yn7T
vT9ESRBXjH6DN9d6X9k7sNT7wm5mfdERBzatnOC9rM/JejQig7PGb/Bm1iepNbDj4ARvbkFs
zpXADfEEr2B9w3njfrGKJ34ANXGutbTcVBi98dUl3fZUb+P5mI7HCRy3bpaDK1VYrW7FOz7S
jZ6OR2KL8PUJCT4mcHpAUl2SFBuyvn6RimfrQzmUSzJZUSqorjctiWfI+ubiCdZXycyZbC/h
AbST9Y0FZuYCeulHs0rOFCNSqJrgt8LMAta3X03QCLynnODNSb649KLWvwd4e5qP4aGuA7yZ
8GU/rcH63QneS/iKJWpgf8wJ3pzms9QYFPs4wV+e5rOLUDyzCfFj1y9ulnOTBhO+RYqCozTf
XDyvNF+32jnkWAhsYViT5mu3Aiaf0/H4JiaVJTrGlAws6/pDa9r6RoTPLj7x1CyExTKr+eqA
8SxSFCQaDRDNxROKgtablFgep0lYV88WRcG5gCLNVzwm4kqVGOwj8Ie+Cd+vE77fIykYnZxg
wv0Eb07zhS8VOo5wgDd39EV7Lzg+eII3876aegO58wnenOiLZA3YiX+CNyf6KBUDZ9xO8Fcn
+uiypaCntiFapcVjXQs4QL2GJ9UyOIcn4/HXIYcXb21kXMGiRTy0IJ5ebi2Ap+ORFKLLHD4b
ogI2i8kSg+axsCBdrhQP18fZpPqFsolIh21dlggLDkzipuMJ3ifGFjxWazbshYunlrQnDvpH
JwNyCpdfWuxZpRi4QDR5EfzdvG8fq/uf//yv//ff//8/aEVb6oOjCmNzm6uhID1a0RG1gI3/
DlnF8DdNGZ1rvdB72XiuySoqrHiAt5fdG5onPsFb17kwpdpA/ZQTvPU31Oz/0gIOqZ/gvfeF
1uLlB+8LB3gFG6e7VvpgR5dvCD20cZDG3GvR5oQCPnxX2BtLG8h8T8bDidVJitNXFjFQyp6X
mN7Ra7LulhzNxVOc53Rn47Vm6hn2QVnCxstt1vJf79uPh/HkVEqtzS8XncKBBwvIn1rCXmnQ
5zEdkFhuVpv1cFAB25XzknZlX6BB3n86II7htBYNvpkJnhbi7zzsKub3O5KxTulaUkZFoU/0
9jJ8gc26DvDmdKwk6eCd/ARvJoA99YaWJw/wXgJIYXwDtoOc4K1/oZMLP2FRp/MD/OUE8PIR
oWe2DvrqGzOL8V0wxbyMAA7K8JPxhOKrX/v8H+2HVwHVL3lNH6nVwazrZDwlpt+tW3tlx+A+
xRXT76Xcppf/9b79eBhPULkiLedu2o0EC2gRAaT+8xfueUBivgGFyU/LHS0A5Ekhwr/U4Qe6
2tMBsdM/yr30kNpvqC81f49XLyKAewu05N956oxu/Sd6M/PrKUb0QOb3Bm9mfppIQJ+0E7yX
+UlNflUFJbVf2L2879WdAF5ATvBm3hcyLGCO/ASv4Em39iNxDl92HfTMDUL99O1SClUqeHv9
iilrlVFZdC4eJ9mafV8qfgzHHC8qB7yCx9qt7uXndDxO4XwLqy0mk3NWtF1xCe/jPEr8XW4d
j+LJrzYJEupZOqPuA3lJn0Sh237Sj18ISDSLv23UYioZ5bGypD/2VvXo8xfiYV/33n2ZemPU
iy6e+qZ9i2jfb8n7RZFPFZ0cOdF72V+RhHuCHuDNHQaUSgOT/yd4L/tzytk6aEN6gjfzP0ul
gK2sJ3gv/2NOguZOT/CKvN9tG1mcx5dfBz2zg9Cu5h+KVSGCNdTW8L/bNr+P6Xj8x65Nagl9
u2IFW6NYoRWF35Gs9mQ8TuV6a5qJuDUDx+b8oSV+yHmUZ77sOh7FE0wuVM+zlF6zgbJB/tQS
P2QdXThmAxKV/FoiJ7Ri6PzNCgJINnIUnw4oFBUbkfonJA3MFOTJ3olvAvgbZRV9608hFIAd
tQd4c69fTlRBAZsTvLnXr/hpCJLSE7yX2tcWexTI7A/w3lXW8EsFi3QneO9fyCX5loiWy9/g
JaXe0eTN5dRBj5w6ku/rzE2tVa5g61U8tCCeetup9PEL8TTL6me75Z4b3LvYlghp3yqdf/5C
PJVj0rpKV7/FopR8ztH2L5RvNHlz+XQ8isfJW8hnh5VK0bBUQSnfktGbMir1zgYk0VoaquBa
ixM/lPKtGLkmG10yZgNif99I/IJRW7irowF9m+gtoHy/I92nlpN18Dw7wZuZX01gA90bupn1
tcQCT3i8wXtZX+MUzeLYX3iA965w5cQNNnl5g/f+haJ+dqG3jwO8JNF3t8fHKXzZc9AzswRq
vVAp2ropSipWvBJO+u7ySB+/EE7rzQlSjL4KgcL7q0hfHWVdZuOpMQxvpXehlzAgRvpW2Awz
jfoKLm+OR/EEffMrBnXf/Jp/FShHWkP69C6gj18ISESran+1LBLYKbGq0KujQu90QKTZVyfG
0zuBDTf+1NQe/E36fqOyovaefOvHzrETvJntUSpwafcAb8/zUQP93k7w9jyf367R4vMbvD3P
FxNlcJ4vwNvzfJZBZcUT/OWM7zLooGd+Cc74qvSQhVMFm2YXUT7po06r2XiaxZRyKz07R0Ip
bF+hsGMjobvpeOLc5cxatBOq3ZVWZL5LufWX+9f79uNhPJHnk95rya1FvyKaRVohLOAM6ecv
3POAhNla1Za5diKY8i0ZUpafv3HPA2JTE20aFtAKN19+5/lWUL7flefT0kDmd4D3nrjkbyVq
r36CNzO/nkIUA2R+b/DmXJ8mWPT7jd2c6fN/Z8W2zwO7Oc/XX9wCzPO9wUuqu6OGvsugg575
JZAzPsutZv8f0ApwS6JvNp7Wm9/2cuesCsobL0r0tduBm89fiKe2GHytze+Hzv9Q1reg+u6s
b9TQd/lzPIonUnathUJky6V3uLrLXz/QMRuQOD0qHlUOYX8wFbsq0VfuAvr8lYAKsV+YsnVD
9W3/XfN8DJO+J7q8oCLvijNj2ZjJdmFBScTgpf0AbyaiLbUKUuUTvJmIWqqGGl8e4K2rXEpL
PYM3/xO89TcUq36DAFf5BG/9C1l7MvAPPLArEnZy18gW1OCyDqGHTg7+ndRqqlQFlHKkJaJ1
P9GUmYsn5GG0FYtJ3E7gjL8/tCKe1kfpoLl4SmLrmc1v1SKokGWZzAb9hYqOGg0v55BH8YSo
YBF2Vti7byxwn+ESkcRbr8WPX4hHutS3jqXfFhrMRJdYhg9HS2YDYs1K4iRUfInA1p/v0ZK/
v6YgpdzAM+1Cby78OePsaAH6AO9lfxruCmiW7wDvZX/sdKmA/PQEb2Z/lqxjB8OB3cv9qqWW
QZ36E7xgs+fRmEm5DETKQz+HYtydLJFkA5tPZo1b/6IsMxgzmYyHU2H10ziHTbCAjSC8xsl5
yP4m4wn2V5SJpWdhRQ1R5uTdnigKlss/5FE8oQ3o1xhfIWNhNJu/Q1J6OiDpVmskOf0jQge1
FklK5zxIfU8HxNEckCnMF7sQqpUz16X0Tf/+AEVBTuhY5wne3u7Fhg6eHuDNrC+mCsCq1xu7
l/O9Oh3B0u4bu/X3U7YkoIjVgd3L+FpJtYB6PCd4BeMblQLLZVJRHpqIqL2miluv4GyZP7OC
wA6lZCbDCVUY7s5gu5Efw9g3uEhKZkz45uKJ3cu3L/Z9LFxRsGzSonQf0yC9XC6Hikfx5ETW
zK8Y5oTc/4tmk5ZICWYd5JenA/JVCXZUuYT7KSwls2Su+LZ34/MXAuIsNWSkfVMwBe+1s70B
34Tvz9ES5OhtRonfgd7c8tWSoXeqE7yX+VXyDwEsmL+xe5mfxlUTzIOc4L3cTyRVUDL3wO7l
fr2mXMDG0hO8ou1wpOtWLn+K8tA/xDlY8fsRW0yxouTvyw3kJuOJafOqtVLkqAncJ/yhFdx8
TP7m4gnyx+TEohYSVOR/UbZvnF2+3CkexRM0znc8ZolJiQznkjaQv9mA5DWPq615YLmgsnuL
yN/P37jnAYUKu+8F/nmKddw/5G9p6Pxnkb/tOoI1FQLVUE7w5ua+MIgFLRtO8ObmvpD6B/0X
3ti9pL7WVHFp6zd47xorJQMHHg7s3r+v1EQNld4+wCvoXr3rKY/j97KlKM9sQ6h2X2CWRiKg
iu8qDcFbuZKPX4jHg2k19xolKoLlZJbk+ka2IdPxhKy3rw0Xbh2cuF8j6z2eLS6XK8WjeF6z
xVyaUi0FdSlYNFrMtzMZH78QjxTrOfKWPbLlWyeLb69/n78QD3ft4SHk16ZW8Cmgb7O4BWTv
t0wWd0sdVEE6sJtP2+57IHjWBnQz22upGOqyfID38r3mJBg1CjnBm/mepYbKTJzg7e0FVuGm
0jd4STvfqL3qMqIoz4xCqKq2yjEvADZXbSF8s+G0SIapk1irGZTwjYe+nPDNxqPdf6iW1emr
gtkjWrLtlVJG+eTLheJRPDFWHGMpRRrnpmCZYZF+INnPX7jnAYnkEqPsWXru+BjuivzeUExm
OiA2MT+XVFSYwX6Pb8r3t9QPbKkaWKg6wZvze2G5AAoaneDt+T0/QdHh3Td4c4ZPUwel7w7s
9vxeQ0Va3tjt+b2Cai2d4C/P710eFOWhR0itRZv5tY3+KLo3G09ruUsLcWVBy7mL8nu9j1rp
Z+NRo2KlZYriJ1xuXzO8MbAFLpcDxaN4IlXn23JWYlZfItgWeIl2II2mhWYDktK5lZgM6cYV
LueuGH8yG8hFTwfEXYz97lKd8DW8l29qhb7p3p+hHWjoSOwJ3pxfkVRBXYkDu5nz9UiL4cqB
dYky30OXkAxXdQ/w3jWuoZOLOsEc4M1vofq2DY7AvLFfnuO7TCjKQ4+QKrk6r8isFe3fTUtG
kCuNqmyz8YTJXTb/9olRVe8tSb7ZeDQsZoWd9bVuW5N8Q5OQcllQPIon0nXhDSfcWYMq7Uzy
jZv4ZgMSKY2aaHfWl2F34693hpsOiK1zlN6ZO1VwG/53VYz+EvFAQpulV9x1/sbygS31gm7h
J3pz/udlDAmmf17YzWzUEsM+EAd46yoXzqmh1dK85Jx+KB5DCgqZnOCtf6GTtuQ0BxwmPsAr
MpA0KgBe7hjlmTuGhg6vkzerBprQb5knmQuHU0wqZCm1W82KEYN4aEU6qIzSQXPxlBScrVZu
VURBa4yyZD6mlDJqMLysMR7FEzKAHkfYfZQWDO6PEQ+cDki6VvFITDIX3N5tCbeWUYvhbEAs
lWvtuVJ4P8IJyG/xwFWU7zeJB4bfAthhfoA353+CKoFOuyd4L/NTSYxaJ7yxm3kfpY4nct/g
rb+g5mhwRH10DvBe7lclRb8UKB34Bq/gfkMpt8sjozzzyHDm50ssViNNAyvJrHB6GwpHT8bD
qWgkbP0Yzp0II7Px0BLyN8oKzcXjPE6tdBLiLmAlsEzKuP0lDfnz1+3Hw3CCxSk766uce0Zd
SBcpB3K9C+jjFwKS7rycm7SWrWXY520F95Nbdv75CwGxclfWRjl3LbBy4Df3W8T9tisH9vQS
ccWUA1/g7aVnowe15wBvJ31+TwKTywd4L+2THEO4qAbPG7yX9glFjgxsgTjAm2lfTehc+4Fd
QfqGCjKXG0V56Baifrvv2moI+aLGdRvkA+fiYT9Olfw4tNKEUGK+hsQa38ntfU7HEwSusjjv
c+6nFdaLXmFcN5YPvMwoHsUT8oE1lM9zKOLADXobBGRm4xEJYWVnfE77UGGuRbXne2fBz18I
qJjfMYqES0038CT7Vg/8+6sH5hQ9wKh64Bu9l/1pSbmDhbYTvJf91TBRQRvdD/Bm9tf8cABF
g07wZvZXnbZjB92B3cv9WktvIWdIO/oNXtJ6OKi/8eVGwQ/dQqLdgLlV8nVGBWWW2DDX28Pr
YzoeTmzKOTe/ELB0LGHBS8SWySnA/WE8GY8TOQk5t/ALafBI+5L6te/wg4ETvrwoHsUTRM4f
4TAmbILmmJfRv0G9dzog8f/U7Bc8sSagktiq+eI8SDJPB8S5Rg27VgnjHbQ59Fs/cMHAyX79
QN9ecP3AAO8lfDEyrKhc9AHe3N3n/9KKTmoe4L3E/iUKiCrKHODNtJ5Sg1n9C7u5w1SS34PB
WZgDvCLdN5ow5suNgp+ZhVBtEhml2nuDZxm+fsJ4Op4QlCmdRYswOvO1ZtbE2iDdNx2PttAQ
FKpG6Nj9KkGZkYIgX14Uj+J5KQiWmmtzBltq/XMmjKcDkmJMMXTpW3mGzXS/fsJ4OiDuXK1z
Lq2YgJmB7wnjv7OGYE9FwALgCd5c5s2pZ3CzOMGbeV9LjI4QvbF7WV/LySooy3yC965xmKdw
xSeMA7z/LawgpzjBS3jf3S4f5/BlRMHPjEKoRuthztUUFfpYNmM8yrvMxtPCJc64iOYMenYt
UpaxNmi1mo5Ha8uhIZjFP0c0nhXWOWMhQb5sKB7FE1XEXLn6U82J7O4Z45+/cM8DEv98KvsK
sX+h4JT+qkRfGaWWZwNi84M9Z86sUmHnk28hwQW8b7eQYE3WwNaEE7w50cepM9rTfIC3J/qo
gfmSN3Z7mi8+ZDjNF+DtaT6tHc/zBXhzok+d8YBDlW/sl6f5LiMKfmoU0np2juTMWUCBzi1p
vtl4WjXJ2iQ3//LhNN+XG4VMxxMGFKHuoi2jZ++WNN9lRPEonpeQYK9VKedCWmG69/VpvtmA
pHR9jfJ2U4KN7jak+WYDijRfNv+Emv8PqD32neb7OwsJ+oYODiEd2M3plVdrFFjcPcCbOV9P
TUCboBO8Oc3HqVSwNHmCN6f5OAx0QWZ/gDe/hyVZx47gA7ukm28wUcmXGwU/NQuRHk7A3V9E
0IJ5WZJvxPpm42n+ugaxIIqh5D8nyTcbT0i3EFsmEQIllxYl+YZCgnx5UTyKJ9J1TEVi5NUa
2Dq+Jcc3G4+IB9LKS4pTwBduh1nIdEBsQsr+vrFvC/9wf7jyFTqCYHloRWHo0RwCmAdasFMu
IMi/Sduwp0Jg++OF3ktNcku5gvKLJ3gzRbZUDe5/fIO3rjMrpWzgJMAbu/UX1BycF9QxOsFb
/0LuMQMOul2c4AUby0tW55ayXA4e/MRPIWYjlEMLMBsJ6mI4qWjxROBwMh5OUWPNfi/J2jqo
18VLRGGcwN7l3T5/YX1UpDdnlYWVGypwuGQgyWyUiL/8Ox7Fk19N85V6L0XFFGZgSyZ4+mjC
ajYg6RbSiVS638s6GtAagcM84sjTK9R8N2DfuPzijHo45skJ+z+dI/+TBA41dUWTeyd6c1Vc
Ih0G0r8DvJf+qTwYGj/Ae+lfy0nR6ZITvJcAEidjtDvjAG/9CyX7Catg0+AJXkGYaNQIeZl5
8BNrhfKyVqg9h+EKfLVaMyE8FDmcjMe5XKl+GDutVSdk2FvkDy2pUw4r47Pr49yctXF+SR1i
9zZ/aGr89C/0YpQjvaw8HsXjRKH66lDXnD0emC8tkW0kGwgsTQfkkVizGEcP0Sg067tCYalk
GV05plfIiuRWe1VTgdPY/55J0n+CyiFHpxNIqy70ZuYXUzcFZX5v8Gbmpyl3cPztBO9lfr2m
go5QnuC9zE9DrwRsJT/Bm5mfRL0bZX5v8IqeyD5ifpd3Bj/zzhDLTSpTowpbZ6zIW/jFZ6A2
PBkOR38sN+5F2b8vlPitKCaT1YHu3PTyRJU/q3EMJIBCKouIH7U7nvSv1+3Hw3hCEoWbSFEp
vXewA2ZWSOUvLZEj4jcbkIhJr9KcoUsH5Vn9qQW585KHV43pFSr9ZetYNfTh4czf1N3pm/j9
MUqHUlKpqCLKid7L/4oTpoyash3gzR0GTosNNYk4wFvXWYhSYZBDn+C9/K9yHHqxyv8LAAD/
/+x9S64kO7LcikSQ/ucGanDOKgRoKgnQ/gdyz4yIBl4jWR5MHlbdfomuvt0Di1vpSWbQ6B+z
BP87wHv5H0IUxJP87wAv4X8j7bnLPgPv2WcwtygqV7DKNZtZWuJtN1S6nownlK4litlmWimr
R7lG6dpkpDw3uz5iMeFjzE4uktJE8dCSzN/ovnG5Z9yKJ4hC9Otx5El7s7SS3gp/k8qjG8ds
QL7bfGE8HrWQPdxKAEfedvMrRGrQkZr5VSqZbP74m/xDtQ59cySP2gO8udevlqZJxZYTvLnX
z9+22fz4Cd66yv7a8x9n9it8YPeuMXPpmCTNJ3jvJ8RHXik7lPUELyAU+FLhIg7gyzoD71mb
EHYJZ1n/jApZTZUVxfVG9qqX7OuNeLSHk7HIY3okd1rFQysyfi8J7Pcb8Qg+8rHcW6Ws12hZ
oUXW+svK6L/226+b8QQxqNRQnVPEBSNd6l3Cj14aDn69EVA4tEBVaA0kP9W9ZB6m9dEVY3qF
ul8vfM8R+S0jWQSok90fH8L3N2gdapHkxj2wm1mflJ51DTrBm1mfFupZS5MDvJf1NSlqyYLR
E7t3jYUitZEUvjnAez8h+V/askPaB3gFS3pZF/VTmC7LDLpnaULS1T9gq9adWWRZ34q66JD1
TccTrmKMVEMYMlu1WMT6XhoOfr8Rj3BkjzQ6azRrNuov5iV13kFamS7DjFvxRKuexUS3R9Wx
JzuNZ+cH/o0k/X7D3Q+I2GmVVgPRZkknpkVpvocdxW923ERATYC7NkJ/IUCa9U1dvT+s748q
HWqBrLftCd5M+FpByJ1KB3Z7kg+ylisneHOSTwo/NIWTlDnAm9N8Uiol1/iJ3Z7k6y2bhjzA
C+gE1IGfLF2GGXTPMIMYakVT8mVO6rS1JYfVb+jebDzauzlRcQ4LlkzEtmJrHOxe0fHvN+IR
IjAhQGBoabr340k+uuwybsUT6bqQhEQVxgZ5SZUV7AhfTlx/vRFQsKLO4LvZ40neo3ck+eZX
qBs2k15rN05bTH+SfCvo3p9SOhRNdqmf4L0nbosJ+OTl/QRv5n1W/O9M9vMd4L28D6ovXNqG
7QnenOjzC0XLurQe4M2JPo2acjLdfICXJPoG0hp0WWbQPcsMshbl3Q7s7/ss8VsymDwkfrPh
aKeGVZ22ZIVcVqX5ZFDcnQ5HhCR4n8RMUJbHLknz4csk0r9226+b8UTCDrpWgOYbTvFnZUL+
K0162Q779UZAxE38X92czkqyHXZZlm9E+6bjab2imsTPM5tY/k/N8uFPaB0m82pL7m7LZkx2
qwq2Xixb7LvQm8moFpWs89oB3kxGe0nmz57QrWuMFCpySemQE7z1+6Pui4bZsd0DvPUT+olT
KDlxd2CX0NBX504Qg8vKg+4YK0CB3sAqSifGpI4jLBFBHgvKTMYT2jANmRFrF0uK/qwSlIFR
9W92faiBhMGt01FMzxWveKcA4KCrlS4jj1vxxIAIi4hpdAQ0zubr1igKymCsZDog8iMQGXy3
+T+TuhyLFAUfGhu/2XETK8RIXP2tINY0Ta0/YyXLON8fUhTspbYkSb7Qmyt/VBqljZWf4L3U
7yESmG1zOsCb6Z9z9iQ7PbBbv0F/8RTLZiFP8F7yp5B3rTnBS+jfYMqTLk8PumOxEB+OGlW/
xDVf7WRm1R9aEA+/VEP7mo4HCzjXrtX8PK6958qb/tCKenrXEf2bXR8KJUHVRq3qVvo3FpSm
y9LjVjxB/3r0tzbp3TR539hC/2YDIlMRQhR20pRUsFwmKD0wVp5fIWn+E+qtMjf/If2o4uOH
/v0FeoLiP6+snMwTvJn1heotJuuSB3gz6+M4R5PU+QDvZX3KpfbkiMQJ3sv7qBZIdpYe2M2s
j/zvTCpGnuAVrK+9GmKIU/iyqaB7NhXU2I8tqs0qZD0sJ2tNd7RkJuPBQuq/+SZhUJft0sM1
xfRx0m9+fXxdDFRjoZKtuGuSfk1/v99+3YzH2UF13udL09HIMN11uER0eTRaPB0QRcLcujkH
a9n2jUVdh/BSbOD7rRXyayrHjJYf8kn5otkV+rC+v0dMsBbGbNLvRO9v+upJo7sTvJf+Sajv
Jb/DJ3Yv+bN4XyWl7k/wZvLn1wpIavOc4L30z3rR5MzJgV1ALvClTWwcxpdFBd20EOHOlSzm
YyHbkLrGc+0xAPzyLJ6LBwua+Wks3SQt9o2T/gf/lfwNO8Fm14eaYhX21wRqz1bkV5BzJzOj
DoPLoOJWPEESRCSSZNVIksI/q5SkeUT+ZgMiqtj9IURuWSPsVSMnL7W+v99ZobhmVieWSl0k
XZOfWqEP+fujQoJUFJId9Cd4c3tfSCxkpxAO8Ob2PigCyVHNJ3brGvuNN2Zys6I8T/DeNeZW
uiS9x0/w3k8I4idqtsn0AK8gfC+dD+IAvqwp6I5RQAsBCe5+UPnlIxtTW5Ptk/YqV/H1RjzO
JcS/Kj+ABdKzGUtaMM1GuZfZeNiUxZe+NqNkv5U/tKKC2HQ0034ZU9yKJ6q1zAitqnWoSamD
VUKCbVTjnQ2IsPpliTvVJlnXgHhqCSUfTbVPr5ApOHmt0BggbYL38YxbQfj+nJBg1qX1AG8+
cc2ZkmZP3Cd4M+/TeLNltWWe4M3Mz8KwPZkyOMCbmV8v9LArSDG/J3hztwE+hH3T6jIB/nHm
d3lS0B2HgGB+2MWsVek9WVxva7rH5OUU69cb8ahU6ojawmM3q8aywlsoRFMG5/BsPGzsL1qk
8MBL6rwuYn51KF55OVLciic4HLFf2HyFEDSdR1pC/IaZvtl4KJpju9+fRLQmy2RbxGWmF6j7
VaMTRO4f8+KInzLv+8Rvt5YgR6ExqSpzgDdn+qAoZKc5DvD2TJ+/zW6ICe4d5Q2Fxa6W5XtP
8PZMn1nSuOYEb8/0cc8y0gP843zvsqSgm5YhrZtKQ+cUaXfrHZm+2XhUqyKSH4a1J50Gt2T6
ZuPhDuZ/fHnQkg4bWzJ9lyHFrXgemb4Gj70WEolbxQRf9l1+vREPYaUqlYGqYV577+cTfdML
ZNrUOmtvzvvStfdPom8B3/szYoJQGifTFyd4c4KFinCyT+cEb6Z95lwzqZBygvcSv1ZLpbQG
zhO8d5XDM5mzzjAHePM+lNIgneh7gpcQv0GDPV+uFHzTNaQBsvmxxdXq35Pom45HWcIxBJxf
YPKKuCjRNyR+0/GwqUJ3EtalJWcqdyT6+PKkuBXPI9Gnfs3gLuhM6Wc1Qu5k+qYDohi5aR1j
ahzz8ns/numbXyG/CfrJGXMdcmMu+T8y0/cjeoItaZbjuAWvpWWDJrsVBaGVqsm67oXenAIK
Hc2sw9kB3sxIe2k92Wl8greuM3KYvSSbsU7w1u+QupWedNg4sFs/H7IUq5Ic0T7AK/goDFzF
+LLN4DsmBvDgB8YmatKTRqWwhB400lcyOV/T8WBB8vPUQoOFkqYZuES0pD0sLV6Sg+nl8d1d
Y2Ja/LaQzH0vGZlxOjoQFeTLM+NWPJGHpKoSCi8xkbFXVNAGM03TAZGZrw4iq6gmPeEXqcrg
aKjpjRXqTrH9tSCPVORHVHA37ftDooJanm/kHPt7ojfngXpBTM6enuC97I+pJGtFgdzL+0gL
S/ImdIK3fntcofTs6O4J3sv8hONKkWR+B3gFU3opwBdH8WWcwXd8DKIJIhrAwMlfFcvlUWCN
AN9QT3oyntAG7AogzUAlKcCHawQSO74q2X6/sT4oBhRNYCI9meeCNT4gtQ6m2fnyzbgVTwgK
GqqEdklFysvVraB+j9mW32y4+wGRdbHGENPlQukWvZ/NFX+/s0LsLBa4hsEJpv2LP4KCq6jf
bkHB8IzA7Jzhid5eg7asTfAJ3s75VLLDjQd4L/MTKmDJQe0TvJf5UTixJhX5T/Bm5qfRoZP9
Dp/gH8/5XU4VfM+pAhn1MSHZrOV1ZVYwv6Go4GQ86Edq93iAtTJn2XnhFVbGhgNfh/n1CZ+c
Ts4t/P+kk34rmB++bA791377dTOeWqAjAJOvT+UO2ancFdY1Yyvj6YAeVsZAUVkPJ8WdNehH
9+ZvdtzMCrH64vsPyDTblvIRFfzHiwpCLyE1kSSAB3ovAWQo4LsyOZfwBO8lgCEU2JN9Gyd4
LwHUkCq74YMR4M0EUIphdur9AO8lgGqhV5lMnx7gJU2IIwJ4eVXwPa8KrGbdyRgb9mQmBpbo
vI2FBSfjCY3ACtGBGFK/yW2+RldQR6LS88tDXUgqKycFi9ew86fAyG8226+b0TwEi3tMT7NB
zc5vrZKUfinL+fVGQERkRlAB0TddWmRmSSLzpe7j91srZIgohk0Yk0KWH1XBf6SqoBSWtKrg
E7yX78X4cNZV7ARvbvGDyD9lW/ye4K2rHAPE3JNjMSd4M6tvBSW7ygd4c6spl5rsTzqwS9je
aOTk8qjgO44BD22ZZkRKVClrd71o5OSlCO7XG/GoQGvQukQSJjs7vWbkpI9GTmbjYVVzHtF9
k0N2dHrFJfc3LX6XQcWtcKJii6LhuKGh9J02qFhT5x1l+2YDIjCOhkV1BitpT5QVs8bt4QT1
mw03sULmt3wU5/s92mWzKzS15T58728QFbQC2ebUE7y5zltLz7pmPrGbSZ/6FTt72BzgzaSP
Stdkm9ATu5ny9WI9qWB6gjfvwVaSlmRP6ArCRwMfB758KfiOS0CLoYEq5oSvoib7ZduafNhQ
XGY6Hg3pxq41XEOSegSLCF9/2an4/UY8LOZMAphQmbPiiLyks49GF4zLleJWPMHdzEOpwDX8
av6eEePZePyWpCZWTWMsKk34lgypDMu70wvUoUuYhgA6I0/L/3zEZd4nfLvFBKVYVs3jBG9O
8GG+1HeCtyf4Ws+aBB/gzVwPw6gzyfUe2O3pPf9vlus9wdvTe60nuzZP8AI+QcPz97Kl4Ju2
IeA8xUlftCVlJUuWpCfGdG82HBXprFVimiMr3bBGS3CoHT0dDxsqijPyKLGl6d6aBN/vt9uv
m/EE3RMCfy2r/wfS9GiRa8gowTcbkEfTEPxX9BhOTrfz/XyCb3qFYsdZa2Cd1NIr9EnwLeB7
f0ZMsBXR5JjECd6cXNFSkzePA7uZ9FkJufW0lGCAN5M+KVFWSbK+J3jvGkst2Ra5A7t5D4YF
bbIs/sT+eIrv8qPge34U2KvWx+ih/5Sz+sSLUnwjGcHZeJRJwQxBsSV10uOhH0/xzcYTGr6E
6LcGoWRWflGK77UqyL/226+b8TxVQbqgsDqHTTYQbcnxzQbkVK/rQ/aIpSbf+6ua+Gh0y5he
IWev6HTSXwnN8m2W/5E5PvjHywjeGkBIjh4seFkuYMh/RtywcTHOflMnei87qXpDKvoAb+bI
vQglu/ZO8OZ1dtpmWf5wgLd+h9we451Jt58DvPUTYtcClizUn+AVPPnlpGbwlsvHg+/YKkjp
1XooGWntkvS98IdW9D7yyPdiMh4sBNhR1YkyZ3+JuMY3Rl/OUnxPxwNhCm/YGbEhZtPx/tAK
FoYjnnzZeNyKp5Xa1K8ynZlJkhKh/tCC9YFmIznNuXhq4Uqoxh2wOrPMtgqumK13mvzqhfD9
RkDRG2MY+qB+hn5sVrbzvj+kbijFFzxZ0j3Rm+viVGo2OfXE7iV/TIWzts8nePMqMxS27Fv3
RO+lf9gKJV87B3br5yNqBWuSWJzgBeQCYKA4J5eXh9xxVpBirQl3P0cUsrqS8dBPk7/JeJzH
OfcTiJnwxpidc16RsmoPD+dXZ/FkPOB37CiNi6pKNmPlDy3Yb2PyJ5eTx614gscxtFYrC0FS
zcofWuFJ91B3+M1+uxuP07im4js5ulSfOzpH/law2deugd9vBOTLYqAtxngMk2r3s4X+D/v7
8wKHTuQw2+V1oTfTPgtRnay38hO8mfixv6OSzPQEbyZ+XUuV3M/5BO+lfQqlZsX0T/Bm4mcl
K/l6YJe0Qw68leXyzJA7DgbROyINKnfSzknHM39ohVoPv6QVX9PxYBHr3Jz69UZ52rdih/+G
9s3F4wyu+78YKBSIKLnl4qEltG8gcCOXY8ateKp/NGJfGfHtDNWyrGJJQM1eKY9/vREQiVDr
/pKsDy+dLE1a0r3w0v36+42AUJj9jy8T+G8onfWbCujD+/4aeUPkEoNcSfp3oPfSP4hJ3ORL
/QRv7i5ozjmzHPoA713n1rBEf33uI57ovQSwS4Gsh/EJ3vsJqxXhpBboCf7psq9c3hlyx8ng
UfatrMJxNCff96vKvkMKOBdPsLlONVzGACXZ7olFlyhcv8zMfr8Rj19vKmCjVhsk0+H+0JrM
34gCXs4Zt+IJPYqGKqE9i6rpkZi+okzabJRqng2IDLQyteiNlKSvdzy1YoVgRAGnA4quyPCf
EfVrYbrf86Nx+DYF3K5xGGps2QnoB3Zzn18tzZIdYCd4c58fFIVss+QB3rrG/jsuLS3G/MDu
XWPuhSWvdePYvZ/P7zoKyXzkCV5B9mxUdrvsMuSeXYYgIwh2FcuK2Ycq54J4xAbzz5PxtGIt
RDqY9eEvkSwjLplV6i8tmb/fiMdvCkIC1nqHZD62renxw/Yqnn/tt18346klpp85pntEn3rm
KSqxYsONBa2nAyJCIaz+G2KAtD/LksaC3l9NqH+/E1AF66Ya1sw1vUL0sTNZQPb+jMChn6Et
96o8sJs5n5bKyVLHE7uZ8Wkhzib5DvBexmdQGlCS8h3gvWusLQw0c2v8xG7mpP53Zh2+T/CC
N/yja/zlGXxZZMg9iwzujWoIkHRoyctePLSE841KbnPxOH3zI6thb9qj1z7L+ZacwDqq8c7G
ozVq1SDNaUVSVLMtSVhClVGC77LIuBVPsDeDSq2ziHAyA1sXkVgYDHZMB0ROjKozWEKzZIks
HlqxQC8H1L/ficfZqy9Sg25da7bE+2ntW0D59kscMiVb6J/YzVzv0RWf5HoP7PbsHmpa6eYJ
3rrCBH79h2Q99wTvXWOLmbDknPEJ3sz2uEjyNXhgF3AJeNkvFmfv5Y8hd+wKoHRnEczI2gGS
I4jx0Aqu93IE8Ws6nuYfrRN1hla5WpYb9RX6hn1kHzYdT7RZVoLK2CV5v3DuuqT2WUdjQ5c9
xq14atFmFqoz1Riynt/+1IqxB7/8/3bD3Q+I1GrkYOOCwWm/jyXF3NftHd/vBOQvA6va2Exb
0uhqNmH5IXt/h76hZa3dT/De87bFDyZb8jvAm3nfw5Q2r3AY4L28T3sJ16gc7zvAW79DbFIk
y/tO8N592LVw9kJ/glcwP3qVFYuT+DLKkDu+BVj8POTaxVmF/6BzTCkeWtHG10dZvrl4IinN
flcJ71iUtLXvilpF6zqqs83F46S0K7JYfzplJOOpS7J8OGJ+l0/GrXhqsVbVd3IH65w1U6pL
Jsbhcd/9zYa7H5DfmmqYJPbQomzZrNgKz1dnfqMJ3umAKlgId6lUM/pZPZq/nfnhT6gcJinM
kvaZZfMl29UE1S/xyWLkhd7MR7WoJPM/T+xmNtqLZLu1TvDmVQYqrWYX+Qne+h1S70Ux2ad5
gvfyZaFCLSkadIJXsFEY5SEvHw+546ogxXmb/0GRsG5Ly8kssY15qVH9NR0PFqcE1Zz/BzlM
3rpwiU9v622ggDwZDxQKkWp1RurLlO1zWOLi4ff50e3ncvG4FU9zoiwVSU1AW7J5KAQIl5Ro
R22Gc/HUQr12vyiy362e/D2XtVvRtNH7KPE9G1CUJExChl96/rqAU+/gv52M/ncSE7RSs3pi
F3ov+0Mq0JJn1Aney/9CIZCSjjUnePM6YyuW1OM+wVu/Q65cgLJmjwd4L/9TJ509qch4glfw
v5ev+ziPL08PueOwIEVioNjpn2FHymXv/KEVujJj/jcXDxaQUJSprQFm6wL+0JI6tI7431w8
TuVYfYOLPixXsnNAS1raxvzvcvS4FU/wvzAMRCfo1CCtJb0kuzrkf3PxBJNrvjwdelOqnLZV
XqGTgy8vhN9vBIRhAhYdyERMycmmj6zMP1hOsD8kMbNygk/0ZuLnb7SW9jh7gjcTPy6Ynd09
wZuJn7GfJckm/AO8l/gRhaRV0kTkAO8lfgal96xBxQFeQCxQBoa3cplUyE0TkWiR95d9+BEn
dX39oRV5C4ZXROlrOh4MU4duzpNAuybbwXCJp0PTl+or39PxBIfjrv42a2TUs2X1JXJ1ddjw
enlU3IqnFjPw/yCHgCXVtKDgEvGVkdnedEDkW42ClzM680vP464oQ8Mw1TwbkB9K1Lv1cFtM
V6HxIyazivj9IT3BXnp2LuFC7+V/ZKW2nix+HOC9/E/ChzZb+D3Am/lf5xJjmFk96Sd6LwNk
yotyn+C9xenqtNOS5fMTvKT0O2gM08upQu85iWio4TpnIlHJdsj4Q0sY4EDebTKecBIBs65O
x6C2HGPCJaXSpqPU32Q84OSUuaNJQ2VMj4MvKZWOGKBeRhW34gkuh+Y3IgEwheQ1ahUDfEmY
vt4IiChSmdLCUaTlFsgfWjE+TSMnkel4MEbbiZz+NY8pzQA/48bvT6DslhPUEGdI5loO8OZW
v1DLSpZST/DmZj8oku6XPMBbV9mPjRKK98lC5RO8d5UZS82+Ok/w3k8YtomWbTo4wEtyfgOB
Gb1MKvSeSYVAN+Uq4X6aHfQusoIhyaj4NhlPK871lLRH0i8r/BgPLYjHXookfr8RD1v3JRIP
q2f7nNsSASC/0g9EBfWyqLgVT/WtY8BQWZF9kbaKCr72Wvt6IyDCSipViZQ4rzCzoh2z1sGw
03RAaKw9pDnJ/zeZHfhYB/+TRQUtKvxZ5vcEbz5xrYhiMtt3gDczPy1Us21+B3gv87OnLWSy
UvkE711liSaYLAc5wPvbTdPD7wd4RVscv2IWcRJf3hR6xykgTKGraoVeq/9JTlCVFfV1Z34D
OenJeJzEiTbtFYSVelqK7+eZ32w8zvyQQ9kX6nbmN5AW1MuZ4lY8weGEDSzEk6il1ZeXSAsO
q73TAT2qvaLQGD20dLJvBZVtozmP6YCwm/+LfY2YmqWzsR856QXMb7e2IBdL7tgDuznVB0WT
DSEHdnuiD7Lihyd4M92T0igpGXWCNyf6tGi2i+mJ3Uz2Ql4pOXV8glek+WxUaLu8KfSed4g2
soeEdKeeTaH7QyvIno3SfHPxhHcIkD0Sl5Q2bVwiYNL6yLZrOh7BmE8xDKO4JDdqS9KwvnN/
v99+3YwnaFsPtTvkmAlMJ5FWDEU5NxrdLmYDIqp+tagNsWpSomkR16svzcO/34gH++Oa1MnX
Pyvn/+F6/2RpwVoU09KCT/D27IrW9EzHE7yZ9pn/pdmJ6AO8dZWpSkFMViFO8N5VVoh20eQq
H+DNvaVaGLLK5gd4AbFoL9/zcRBfBhV6z0BEEbi1igwsSZO1eGhFRx+9qk59TcfjHA7ZSRL2
jqLJDrhVBiIv6+/fb8QjQhzh+O2Bs9Nii3iSjLLKlz/FrXicwpkaq/o1BqolA/Kn1gy/DqQF
pwMigVp9jVQwLc65yEGERg4i8wE5QQ75xxB/pLTFy1wLy9/O/H5EWtDvccnRiRXFlGXDJrtl
R0BLS3qin+DNVee4JWW7rA/wZj7aQwwsm4Z8gnevMvjCZTM0J3rrt8i1FpCkAM4J3voJka10
zEqXHOAFr5ahvKBeNhp6x9QglAIrNgb/4xwhd1NZJi84Ighz8YRSoCo237YoCNkZE1xhQ2Nx
er/kB3PxQKHa+mPc09INejCZGLojL6OXicateGrpncNXp1dE0KzO6Rp9Gd8Rv91w9wMiU/8F
NehVNNuzu0pfZshIZwMKPUu/oHb2y50kVbTq5E/ob2ek/430BZHCcy1LDQ705pRkD/HL5Evw
AO+lgOxfS0uKpj6xuwlgL5WyIjNP8Gb6R4UtKzJzgPfSP3HmnixEH9gV5G+kLaiXk4be8TWQ
ImJgxKD+TWpaW3BFk95QW3Aynoe2oJ/BtRsZJZ1OFmkLqo3SkXPxQNxhjYQbKGGSK8Fk7/8t
8nf5aNyKJ8ifLwzHALhvOssmu1ZoGv2G/M0G5OTPmqJWVrHke3WHuPR0QH5kNuxMEA4u6abD
j7j0KvK3W1wQW9GscsuF3sz6Qo0vSUxP8HbWp5rkpSd4M+8zLD1riXGh9zK/aMzMFt1O8F7m
p/6XWvLHcoJX9CCO5AX18q3QOzYCGjq/NYTR/C1vyRKJLsnDjOUFJ+MJpUAkCJMuIOu5QsYi
ecFx4m8unsjhMTZhIIUG2YEg+nlxmcu24lY8IRNTfctB2BsDJY1FFonLjHsQZwMiqoBdiImb
U9qt8oIwGnGaDQgr+Du1VxP/DSX7quKpD/dbxP3+jL4ghTlmckLvAO8lgOx/JyVnZU/wXgIo
rVTJDqAc4M0EsLfSNfsRT/ReAsgtNHWTPbEHeC8BNCkISbJ0gpdUfkfqgpdxhd4zFlHtZg1R
YnIyd3yFes4SAjiS/piLBwvFaazChFqz5i+TjVS3kn9z8UQezySGf5t0TZroLqr8jgng5Vtx
Kx6nctpbNxAOb5Hk63yZvvRo6mk2IHIG2Frk0FtLthos43+j3N9sPNha9dtGrdD8F5RdoI++
9IIhlN3qglzQkoNtJ3gv52tQpGeTfgd4c7ef/6WUzZwe4K2rjEqlc/Ied4L3M3vJavcd4M1d
p1wgK8fyxC5J+I1mTy6/Cr3nVyFgXLl2CCO0LJ9YpC04yr/MxfNQmKmRIGtSIdkwsEph5mU+
6fuNeFhNfYlUTCXp7tCWKAABtlGC+XKruBVPKMxUxhpmtVwBsoIsG7QFZwMijyZkHyuLX+DT
nX4rfkG9v+qV/X4jIDTSMMfjZs8kdo7wTW25D+H7G7QFtVB2huIEby72xo0vmQM6wZt5n/ov
IGvTcYD38j6rpVp2PuEAb+Z9vTidy2Z0n+DN+9CP1vQnPMAr2uJ40HZll0+F3fSpcGbBZoCc
rVMtkxYcnMOT4TiHCxVmpUZNpCZ7WcsKS0wnzoO8y3Q8rNFqK+CEtiflLOOhFXmxkbSgXS4V
t+J5SAt2xt4bNuiQpRU/Ly04HRBRAxNsERElU7E75GamA8JO0VXCCAY1mcP4iEr/I6UF1d/k
SS5wgjdn+rD4ay950h7g7Zk+yOvMPMHbGZ+0ZA7kBG9mfOQX4ezozgHenOlT5wjZfXiAlzC+
QW3XLp8Ku+kjosKPXh70H3Uyv1qWxCP6qnb4NR2Psze/REHv0LVqstTW1jjh2ZDyzcYjNb6o
2hCaZt8s/tCPU77LpeJWPEH5NAS/uQXlT+bLl1G+0R1jNiBCrMAeEyJAfrBjjY/IoJ10OiA0
FSR24ieIyUH/D+X7JysMhkN5ch79BG/OsWiJybZkjuUJ3sz8rCika7xP8F7m16nUrBfLCd67
ysLFt1eSgxzgzfuwl5r11z3BS5jfq/d8nMSXT4Xd8xER6o8iVQ/dh2yyb8VB3MQGE5aT8QTz
Y0WLEZWmSXa+ivnZQFp6Oh7xX6B19mCgJYui/tCKsQ6nM7/db79uxhMi0dzQGqnfNHp6pHfF
DPnYM3g6ICLfa5UMoWdf/Ws8g1vvAwO5+Xj8DljNyK9Pikml13+qtPQ+Wvf//uf/+V//93//
j1bripG4G6dV7hW4e/4hOfmw4EeygJD/CYFFBSl+5U/OWR7gzQkwKJA1TjrBe7cZ11Kzlfcn
dusaA5ozqew3eIC3foNCVJ4+pZlhjwO89xM2DNHi3CKf4BVknAbyy3b5iNg9HxHutTrhE1CE
rCzUEtM43/6DlsvJeHw7dKihDtLDAy83MhgPreBGI1O/6XicF+ljihdb1urSH1pi6oeDFl+7
bERuxVMLggk7d2USwbQ6Ni4xrnnZufL1RkC+Ps3flMaRVU7aSPpTa1bo1XXp+52AiFvF+CcR
YpaN20dccRXr+xO5WEU/pzg5fHuC95I/atGvney7PMCbyR/5jyfppXKC99I/4kLZ/rondi+1
ghg8T85UneCtn1CxlmxH34FdQC3aS2W4OIovJxG75yTCxiGiUat2p6lbqd9LavE1HY+znhgn
JQXVDkmRpnhoQTyqozzsbDzaIqGMSPZU0kvFs+Kq4VfnEfW7fERuxRMkjrg3CGM8Z+jp+u6S
gvVLpvT1RkAhfBlOPGIdkh6Zs0QprX35/UY8vss8JAilVdZ02/JcdvHD/P68smK1IEnJbNWJ
3kz60PdXMl31xG6mfFxatub3xO4lfNzKU5wv1dT4BO+lfMZFstbiJ3gv5YMYT0lehE/wkuL7
qA3uMuuwO9YJUaf1Wwe27jekatk2xRX2Ne2RHHl5Bs/FQ4WaddMmgLVxLh5aI6nT66u22O83
4hGOJkWsUXpPznHQGnu/h3z3b/bbr5vx1AJVnZSzYUWrkNVUhCXdBDpqu5wNyNfHfz4abcs1
O6haV81CjSZtpgPqathjsh8Y03rac52+H9b312gqAoVmTrK950TvJX8cFdy8qCLsnrqRVkCz
+b4DvJf+CZZGyXr0Cd5L/7QVv0Ini6kHeG83C1J0OuR6Wp7YJeRvYKZil1mH3bFOcB6HTQjF
9yGbJfVU1+jr8Es5uK/peOK7hq4qlZ0tYZYsLenxUR6onUzG49dDP4Nb80VCZ+m59YmHVpC/
l42K/9pvv27GEzTO3ydUnc1qheRtYxH5qzrqLpgNiP3uxBrD1tK7ZWujvCTlJ6PrxmxAYg0i
+69M2XaJOjmF9+F+f1JPkbVQdo7+BO9le42LZmV1nti9bC8EEpMNUg/oXj4vvUC2W+MEb/3+
kLBkiwoHdu/ng1pUkp/viV1R2W2jyu5lzGF3bBJaaSYVaiUkrlkr7bLC6LGJjXIuc/GEZLQp
dgjblKyr9RqjkaY0arGajQdIuzYnEZCeGAozoRUsQkdJvsuW41Y8YbCBUh+10Gjqy/K8OVuO
fxsZGvG82YAkdJv8YqHRGCvpYfEVtXd8OQP1/UZA7AQvDJMBfd+17ArNSXB8iN5foKMoMceX
na0+wHv5HpKfoVm/+AO8mfE5Dc7aAJzgvaxPpUCyqHJgN3M+50nZE/sE7/2ESqVpcpjjBC/g
FSgjFcXLj8Pu2CMEhWMCMFFomJxnbwWWGOYNZRTn4oGwe4BuypGyTDaBTJo9/Nssx6i/ajYc
RnNCKUxdKNkv5g+t0OhrOkrvXW4ct+IJXw1UJ+Tcuy9QthK6Yn1CaOm32+1+PM5htTJ36AiY
lwhaERC+VFr4ficgEeDOYaMpyffB7OD7h/T9SQ1Fca6evHcd2M25PS01KYp2YDczvf8PAAD/
/+xdbXLstq7cEQufJLEB/7D3v58HzEiTquSJB6Jp2rnxTd0kP1o500ON1ASBbt9eU1Itn+Dt
9T3QrM/PAd5e38sGpRzYzfU9zNcfn9gvr++9cjj6vRwO7L2KMreqnJ7cWFPfo5GDzhyfKNVV
JIRaYxg5eQSwKBdPRoYms3yoYq9WoVHP86EVTXzXsbt/3W9vN/lEpc4X3kVX979j3plvTX1v
kIs3TagigzWLgjJhcrZmldK7TMr8+AQhbTFSg9qg+6XZg9y5rsRfqfcDvBMrl9jrJyXfE7y5
vhfBItnTmgO8WfX10jlpNXKCN9f3/A+lbCTyAd6s+h5dZVnZ9wTv/YTm0geTc+MneEmFb/Am
tlcQh90L4iBA37zFeIBk+48WVfgqXSml92k+LnpMhVkaheVErpBNS4QFGg8qLtN8oreyN4WG
qlkv+SUdlq4r/ny/vd3kE9W6xnHHEbRuSbPOMHlZQeiyBvv+CUIVQsP6rwce+42dyg9HJ7vz
hEz8adDFatT5sie7c+1JP135cVr53XIkS3qRLXgoLRsq2W0d2Py1mew0OsF71aj/oZLO8T3A
e9Vo2AH2bLjWAd66yhEiFy0kSUX/BG/9Dv2tW4CSEzkneOsnFF846clfygleUocc9H3ZKyPE
7mWEaAwRA3NrpMl5BVxyoInaBweAk3weLSaILqQEqbXcXSRrYvva5XD0xzSfsENApYZhf9KT
dUie9PO4pUZfCSG3+IQa7WBdAKSDpscvlqjRa8eV908Qsu4/HrLIijTLarcVTUYx6/vHG+4+
n4qm6irU/AWVzSuY7Zv86WL0P+Ud+IgdTVoHOnZzJVIjRzzbafgEb9Z+Ukyy0xsHeLP264Uf
TV5J4+gAb/0Oaye/s5I+7yd46ydUbEU5mYRzgldUInGQ32evlBC7lxKi3Bmldq18IxJ4ifYb
GclM8pEi0HrnWjla9HKFLlkzY9J5YBw9yYcLS5SKRRVZkoW7uGiBtPA/9I/329tNPqHipAnE
dografbIdon2Ax40t04TMgZFcHVO4R+ZrUTailrxYwLkD3fcfULN+URR1W83p5RVs23qJ/Qr
/r7fPhDDIDhp1vtC71V+EpuLtH/gE7xZ+Wk8qbOe0U/wXuUnLjdbtovpAO+t+mktrkWSwTUH
eK/yAyzJUaxArqj3XVqFxTv4FUZhN8NCWvh4NLM4c0res5NDhH8/fZZB3+EkHym9ETTrkHYg
iktWnD0P379zbLgQA1PUx6xzslM4LlpR7YNBbp+9gihu8YFHr4N0dLlXa0v7K69odvAN7Ejx
zRKq5Ey4IWi4MKXPnpdIWPrzHXefkCBFah9aBck2usLkpulX8f0Y60CsxV8AaeH3RG8Wfq00
yp1IHdi9si/cADXZefjE7hV96jIk3cB0gPeKPpZSOydF3wHeK/pqKyTJp+IJXlHu49FR7yuM
wm6GhVR02cyKANlZ3LhohfQbZehO8pGiqqakjXr0zSfF3xI+/ZLPxzQfLvqICukaLq2c4+MX
LenTG/lG2yuL4hafkHHV1LVs69Rd1O60Dhw3Hs4SquDKjyMsrhkmm2hmbZb/Lv4uh/M/PkHI
n1ZISujSTxpmR07kd+Tk8yMnu70DbwQDn+DN3X0RB56c3z3BewVfWAJiNhn4AO+V9a5AKmcN
wQ/w1u+QtRW07KzJAd57HyoVTAbqHNglvX2j891XEIXdCwrBphECGqd52Z1UDCavEHx94BU9
yYdKnIWCGWKDnjdfWTJp0gcTn9Pr02qr2glRs2dtfs0Kq2iiK+vrv263t5t0HiPGAhU1/JUp
eai0aMSY8YrQ+ycIVSHiyt0eA7npEeMlB/DD3r5ZQnGs232NKPaB6RFj+c0FXqD3vmvEmLJF
qhO8Wfb1wskS0IHdLPpayfpIHdi9kq/5Gy49cnKAN0u+XjDbGHmC996DnQto8oV1gr9c9L0C
KOxeQAhGklp9NCRhsscKlwRQYOWR6JvjQ0X8VQXctIX0S+Ze+0Urqnx9EBAyvT5GvixMbL1V
ya7Pio0kAYya+l7xE7f4hH5zmSS9O6XohdtpIYiXhN4/Qchv4956zEX59indpbhE9eGlJ+LH
JwgpkKqxL5OB9CyhuX3Tr+r7Tg/BKJgkzVAO7GaxF+GlyWf4E7u9wkeUFXsP7Ob6npZeazYh
5AneLPZqaS2ZQHmCt9f3zJKToSd4STff1QFOvHxfKRR2MyXEF9ilhIBxT2YcrBJ7l+LofZpP
FOu6Eol/W65ic3z8ojV20aOCy+z6tNZdSTwGUvLT1StOXvyuGB3pvjIobvGBEll91KL5kRsk
4weXlfhG5kWzhKo8zj75WbtMJ+d+fYlvlpDfZ0i11i7sO8CcFvgt8f27XQRNkq4oJ3jvG5cf
JzfZudMneLPu66W2ZBD4Cd5c5pPSKTl3eoK3n+w2SrpZnuC996E9ehyTyu8Af3mZ7xVEYTdz
Qpp2A9d+Jr1tPtsdze7O8Yl8uAomWFkk6QqyKB7OLucEPj6xPFY5hpGBqEJydDcuWnK2O6ry
vWIobvGJeh2EE42Rb9qQ0iaCX1/lmyXkNxoThpwVpbzwWzK6O2wmmCWk/kQgI982CUO6bDnX
PvrThd+XmAgiJZv9acVTdtmAyX4bwSZJsXeC98oAbHGmlE0pfoI3y1Fz/ZbNKX5gt64xMRSq
yeHRE7z1G2xCpTdN3oUHeOsnFNCS9eI5sAseKmMbmVdUht2LMlGunSNBLGZX0yPFK/jUPqoJ
zfGRYtoxAt6YSZJGlLJEu/kbfHT+N8eHSoOqSGC+rba0ofWcp8ctC8FXUMYtPqEqq/8kejVr
DMnn5DIbmZEWnSOEBWKE/UkKs0X8FW3Hz9awP9xv99dH1ff2wFWa/4DShuNzg1k/XYn+pxwE
QZIprCd48+mzFcwm2D2xe2WfSqmWzJI/wZuFnxVRzQq/J3iv8CMu0pIn5Cd4r/BTKDGTkXaP
DvCSKuT1eSDCmZUR/3ZL+kkzoMYVDbNdsv5+WMBH7PpNPMvHf1KtOpn6iP+QrIPgil8hNr52
j57lQ8VQuFlFIl+obIqdLanatet+h5PP200+IeJq1dbR/G+crkIuKdoNzKPn+ZirWGEVtObX
ZkdmbMF+f5DK9/EJQhUVqPfu6985OSv56x797zUQJCkxdZ4sjB7o7cfPIMna7QneLvxa1r7s
BO8VfsK+686OXB7gvcLPwmEnKZ5P8F7h51+LJGfuDuyKil+/rsD4K+0lK26GhjTs3HsjVUo6
leBkUuk/Kn7XTjKzfLS4Oo6mEyVC41xBKS76ctk3x4dKrxEtqFC5WrIKHhct6dK7kkl/3W9v
N/lAQeuRT2PMVbIN5ItsBOGyb/f9E4ScBht3tW5KSbcBv2rBxokArq3K5wlxJQZstSPV5Ls2
LvqVfYtk3ze5CGpJWwg6dK/uk3jlpI2jn+C9uu/hCph1a3lg96o+5dKzwvmJ3av5mka7c07y
PbF7FV8P28zkBzzBK0p9A+NoBHppipthIS0cl6D7m6sm+6VWab7LcI33aT5SnEq31ir7/5NL
VPoSyTfIiZulwwXQmmDYIRomzRB5zSHiyDzw5PN2k0+It4gJ8S/LBQslw1wWmQc+5kD+cL/d
J1R9K0ahxw1Ie5bQkkhaS9xx9wkJuDauBA0QIGnhEVf9ar5PT5rsNg/0d2dyeu3Abu7oi61R
Uug9sZv7+agkX5iB3Kvhay1Qs27AB3jrt8fV9/89+UZ7YjfXl135QnKo/Yld0sl3NTwYL11+
iYh74SBYRWsMLYhAsg4WF63QeDbSeHN8qLgc6siRA86abArwi1asj9F1J9/8+lS26K1iiGnV
7FTJkmHV0TjxyeftJp8YJ3YJ7rrVhQRysjVn0TjxuK43S6hKtGsotOqiq6fjQZbU9XQk8mYJ
CYGRb5Aserjz8SC/57kLRN73jBNHPqFlHQOf4M1tfFQwHQh3gDfrvVa4pseJn+C9qq/5awGS
veAneLPqa66UksXHE7z3PvSdDnCy4fUEf7nyk5eyuJcNEsqPEJvrMMge6C4SfqO+qjk6VMQ0
qntKHTXZUr/IKbpfOl9/fGJ5GkOtXbm11rOpTX7Rkj6+kfCTl6y4FzzBoK6Qoatwl/T555Jx
Ypbr8fV5QlXVfzpMKihqaeG34sh95CMzT0hUagVVjpnv5ET+r4/Mv9I0sJakk9MTurm2588x
S7bLn+Dt1T20pNPSCd5e41PNhr0e4O01Pu7J8JcTvLnKJ6Ulz9UO7JKT3FETvb7ExN1YEAyz
3gitp+Qc/CrTQLvqOX+f5hMFu6i5uHC1ZC/iqhpfu/aHnl+dqgi+7uL76pq0U8I1FaRxjU9f
QuJe5gSZ67wGcVr4o0p8s3yqtDC/ZAtDnORDdVWJj66tiuYJCaE2fx5Ys9rSK/Rb4luh9L7P
MTCfCeLYzQW+6j+yZGDECd4s+cIC8IZb4ObiHhdq2XGSA7xZ7tWYHM3VMU7w3nuwYkS9J4vM
B/jLi3v1JSluRoJUV/Tmbw9/YVm6urdG8F3xeZ/mQ0Wcj4skA1ZJPshoMrX075IPRse6s+vT
NEqVEr7KLftcKSu8KYeRICeft5t8Qr01qmDqd7Pz2moWyDLq3ZslVMWs+v9cJDGkc9OWaD65
tHP8+AShGD9BoqZq1pPnQHHV/6Lmo68wC8zmXW0WLtka0IJH5QJ9/F0GhpIti5zg7QfgtSUz
dE/w3ttMoSBlmwoP8NZV5t5KTdrvHdit32AVLapJv+8TvPcThsl4dpdxghc8VkRHA83tpcBu
5o50l3YgbL6ftPR58QrfF70cx3yf5iOuwKIlX6Pmxsk0HllSdMNOo9PIWT7iYrJVV1/SLGlD
IEvO8+lRs/zD/fZ2kw+UyOGt4JvvSLvJyq8VResI6fvj/XafT+8RcKPcQWvSAtQvWmFjAzyq
ic7yMWqtdutae08PH9nU+vx0efwfcjAUf88nny4neK/yk0cnUFL5HeDNyi/sc7PjoQd46yq7
XC9JE5ZA7tVUxMV60nL4BG/9hB1raZBUfSd4xUG4jEaa+0tV3MscaYQCDaM4mo0gL0t6OJVH
LjZzdKQAVRcV4j98EU3e42XJNFKrI9E3x0cLNVcTjVsURZP1lLhoiei79kk/+bzd5AOPCXrf
TEpD7pbcZcCSEXpXSaOmx1lCXSzmxHzPRNaT3lt+1YqyKA5l3xwhDB+oJhKVXieWDlWaqlv/
yr7vNy9EK5gdgjjAm/UeF9RkE9AJ3qz3/ImbdTM+wZv1npWGuUPPA7tX8xkWzQ5gn+Ctn7A1
KNlwxAP75YrPXpLiZhRGbabA/vZgS7q++EVrTsJHzWhzfOTRpd86SuuamzmQyRb9v5+DD6dc
ZtlY+IlwAzHFZJ/CouAVsz/fbW83+UBh9cedVejA8PjGcufgS3o5L+233z9ByJ89FDsmqX7j
SbZVcImCFRo1284SipbUpv5y970GpQ3F51IAfxXfj/EtpF60Z88nT/Re6adUONk6c2A3dxJg
oaQry4HdK/tqK5Tszj6we2Vf941j1iD/BO8t9VWLkNRkqe8AL3gV02Wpwl/F+ArCwHtBGN0i
LaeKK6Vsix0VW3EgOjzgneQjfr8yx4u4oXJ2d1NWbA6xj17Ek3y0+N0N4tIPkDQ7jegXrSiN
4aChAF85GLf4xIAakCn13tA4WdGPq1aUxi7d/t4/QUhd8EEXguhVheyA84qoH+LLwPGPTxBq
0Dr7zRZH14BZQnOxiL/S71vtC2u4g+R+gyd4r9hDdYWZPDU9wXvlXhgTZrNdn9itaxzV2fQR
xAne+g2ySNHklPiB3fz5tDzzdFMf8AleUecb5dLhKwADbwaUCFX0969v7RWzBzlrIokv+9/e
p/lQEXRVxAhi2CXbn7hEjvfLoeCPz/AJtVdbdFm15BZjDR//cweVPnzFX9zi48LNFLqxQZPK
LSsm5ryQ/17pu7R/ef8EoYoui9gfQs16dg5uNsft74Tkz3fcDCEz31s6pWZS0wY9v1POC+Te
t0w5ay++4rk79wTvVX1hE5I14TvBm1VfK8m3zRO6V/NxKy2bl3yCN2sqKkTJ3f8J3voJfUtf
wugrV0A6wAtUBV8Gz8db+JWBgfciSipSIxcspJDO1SlLjHrqZTvS+zSfKOqDdagNBSVreFpW
jBTiw+ro8h08y6e10EfVXCGJZq16Vpy+E1yq8r/ut7ebfMIDRQWYyTUfNM2e78qKMQ7SQfz1
NKEIivYNk/9DtCWtTWHJL4ho1NA3Tagx9MrdbzjfaCSD62HSOPNX9X2ri2H3ZUv6BZ/gzUW+
6s+ybDPfAd5e5KMGeSfDAG8v81XNWgMd4P1lvposaZzgzZ+wFtTs7PMB/vJC3ysRA+8lYqiw
gREhQNo5ZVGdb/QCnqMTJS7s3TWfyyOuW+t8hgNnm3k+zBB+yBxJe2mnniVzrkPF94rDuMUn
6nwcXgXSnVC2sAxrzqnpcvD9/ROEKtYYcTWq1i058rCqzjfyrf4EIVMygapCHbKa/LfOt0Lx
fY+boRYTSdb5DvDmOl8rYtmAsAd2s+zrxXq2XnKA98o+4cKclX0HeLOo4iJZN9gTvLnS5zuK
ntzTn+AFukIuCxXxHn7lYeC9PIzqC1x7q0zSkhP7ONm2/fd2PhxV+ub4UORhAHRBIIJkmwUt
Mcz7Q6Vvlk9j4E4u+pA4++hbk1fClx7Jf91vbzf5RKXPTE0V4gwhbQiyptJ3OZry/glCFWIS
qkqovmppF+sVlT6Eq+Hqj08QathbU4NIr0w70Mw94X667OOvMDRMTsstyateNl6y3zpQe3JQ
8ondK0Tjz8R0ct4TvFeKPrwAs9bVB3jrGrNGfSJbPTvAW7/DhlL643w1cxse4L1StHOBbD7i
CV4hRWXg6oGvvA68lz7C0pTgUUXhZPskLZnxRO0jZTDH55FcI9Fp4togPVO8wosaDUdKdI4O
F3KFq4hWhdOGn0sGZVyJjnY+r7SOW3xcU3bhrl1bV+rJjO64aolwG1gHThOyTjGURb75qdDT
XnsrCNEoMnmaUK1s1AG5o+/pvjYK8KdL0f+WeWBNHnGc4M1lSC3pLqIndrP2k2KcNEM9wXu1
X+tFkoc+B3brN1hdKnVONmuf4K2fUNUKSnJ7foKXFCGvZlbjVfyK7cCbMSRCQo1NqWpNDzGs
ULI6HPGc4yN+v3J9yIpINsv6B8qKImS/XJ+PaT5cXE7EsHetRDUpLHhRiauPZopfoR23+IBv
xxW632oNWSw9k7HCb2vgsvz+CULG0KFiZ3RS7Wttlv9BaFSEnCXkeydnpMzcjJK7DZjcPf1K
v+83EASJaLLkWOyJ3qv6xJ8AlixKnuDNuk9L0nnpCd2r+Sy+kty74wHdW+vTXjB7fHOC9yq+
cCGHXK//gV2i90YeMq8QCrwZEuL/3e5apVn8ldR7umS8REYznnN8pPSOQGIo1VrSDCsuWqH3
RjF6k3y4SG/iL3YGg2xlzC9a4iEjo1LfK4TiFh8oHKZ35HecKz5NtmXDkvkfwsscyvdPEKpk
EgE7rXXKDu7Nuu39w+VntMOYJSRijyz1p0t5OkZvqvj/q/d+jH0gctHsjv+F3iz7WmnZZ8YJ
3iv7ajinZ4dNDvDWdRag4q+S7GzsE7xX/nEvkEx6OLB7C5JYi4Ll1vgEL5AX2EflvlccBd5L
CxHTKPa1EH9JizpakkGGKqPW/zk+Epl3oETRD61JJ09Zk3n3GC29fBnP8eHSqYbJhzirZAdJ
VMBXaAv48+32dpOO6zjGGC22cNyjZGMBLNkeu0T78/12n1CF7isPpJp9Zi1qOGQbNRbM0vEX
JqChxrxWdpodJreDv9rvW/0DfdebbZs7wZsb+8JkPTnBcYL3qr2HJ2DWcfsAb13lqM6mrcie
2K3fIGsrEY2QbDx8gvfehVVLdnbhAV2gJJhGB22vHAq8kwqARfz7A+7WVDk7VLzkXLdexmq8
T9MJDarWuAmTdcgOYyypW9qlEP/4xPL0sD81Jm3pcCS/aMHtRq5f/ni7vd3k45qtGrBrIpd7
LWsJ71ct8cVpo5a+WUJVBPkxYOJbJc5KoxWjA/5yG7X0zRKS1pr0ZuILVZMmI7NNl79a7weY
B1YsgD2ZOXmAN0u+HkODWcn3BG+WfC32sFnJ9wTvlXxRmZWkJ/MJ3i76IkYgLfoCvPc+tF5q
w6RuPsArSnyjhFZ6pVDQnUyAEHEPpxJXFS3548c1eWpDN5lJOmEMo34NV23OZ6f7CtoosmGa
D1CLSRvDrpT8UdCSgONxSAi9Iihu8XmEhNSHjPXlEd4aEgL1Spm/f4JQ5dp9efzHg/73bP/b
EuHHNCjyTRNSJm4sav7ot+TbNq76FX6fFn67/QOb75PTISFP8GbFh6VmD9NO8PYiH2U35E/s
9hKfJJv5Dux2tSeQni1+greX+GrNzjoc4K8u89ErhILuhYQItxrudADQ0iEha+p8NpJ7c3yi
ZOcC24URUNdkoNWyOt8gsmF6fXoNtxXuTRRqMmqy9BVhzWaj3cUrguIWn6jz1SbQDdR/vOkj
0CV1Ph6Nik8TqoLQ4iypklB6dPfr63zThKRVJYPWoblAzq7Qb51vhdz7njqfFLSkKdoJ3vvG
Zd+RJ0ejDuxmzRdW2kkvjxO8ucrXCqXnMw/wdt2XbpM7wXs/IbSCPTmbfYIXvIdp1FdPrxgK
uhcTItUf770bqaZTQmTFaXW9rIq9T9Pxnzyw60lp+PSzyBX5VrQlGg9Od6fpQFVmV31syaZE
v2SN5ht08dErgOIWmyjWqW8uXH4Zk6QDKJYYRiOMNhmzhCq7jEVwJSvELd3Ht6QIO2obnSak
IlJZGVVcl2dF7Nxh2k/XfF/iHIjJA3NcEcjx7/UO7MV/VUn/mAO8V4liJLylI3af4M1a1KI3
KKtFn+Ctq8zhq5NMWzuwW7/BJlo0GwJ8grd+QqFaTJPmFyd4SQVyECdBr3gMuhePQS4P/M1j
QqjJPZRftKbT8Kpi9z7NR0qEYqgScuTGJq3Gl1i54SNd5FIbzK5Pj4av3knNZVzWlrsvaAjw
rfxIjb7CMW7xgcfOh5urHNdwWZtVWLL3IeCRGp0jhAXItwnkTyJfpWxSqV+0YoHaaPMzu0Aa
JqINlABMkr26s64TP12M/oe8A7mwYtLF4wBv7zY0ydbQDvBe7adSGiYPiZ7Yvcqvxp4xOe58
gvdqP6JiyYyVA7tX+XUqnA30PsELlIWMoorpFZBBNwM/GASlNU7/8GnJbKdve0bv4Tk6Ump0
GJohql+Ze23FRQv49MtG0I9pPlwQO2DFRtCz8d1lRV8rAY5Onl/hGLfouIKzSKgmMzIEyw5k
LLHGGZpGTxOycGHyNXLR1zXtsWwrCDGOTp5nCdXwFQCoFsPeyXbqX9Pof7VzoCRzhE7w9nNn
wOye9wBvV3ydkgOxJ3iv5mtatCW/wxO8V/MZlJ6uOh/gvaqvWkFOvoNP8AJZgXrVMBXv4VcY
Bd3LChHS7h+yo4BqOt53heyrwwawOT5aEFz1tThIt5qclPaLlsTWXTpgf0zz4QIMhNhcV7R0
hveaARO6jF/+6357u8kHCruORe2goJgd0oIluYL0eDL/4Ya7T6iq/8XNqnTIdjvMyqR/eDyO
Cn7TK9RNwW+65rqckj6ps/0Bv7rvxzgIEsSLKusgeKD3CkCJCZKsIcoB3isAKxbmpHg5wXsF
oD2yy5JFvwO8VwC2VtSSk3oneOsnVKLieinZonuAVxz4XiYexAv5FUlBNyNDuJKxRiaZWVoA
Ljnw5YGn2ySfsLqy8CZmMKw1mxa34kk2Toub5MOFXJj7/aMsSMlfBS85kCe4rJP9db+93eQT
ZtAU9t4KMQGSLDQvspAeTxjPEnLxxzEGrhTOe1utZWBY+JslJNTFdxsGDxfBr02W/hWA32oj
WEvLNn+d4M0dfrFVSg7wnuDNHX7kf6gkA1cO8F5pb1agJztRntit3yCHWVF2kOOJ3b7tSPeO
neAlp7yj+ssrkYLu5AP4jiPmMrQThZdvdoJ1yWxGvZxgfZ/mQ0UZ/KlkAo1qy05nzLlh/P2Y
93I64+MT6xNzM75GvjitJt+9EVGzQr5eHsP/db+93eTjwk1bdJD5Rg2rSrqatKQ8Vkf1vllC
VbpYxSiQ1ey7M6qEKwjpFaGPTxASFpd5KL03sGRI+6/c+zc7CVLBpFfVgd3c2ffoQk+e8x7g
zZqv+YY0+QlP8NY1JmilJlMAD+xmzadFena++ADvvQurfyuadEA7wSuKfDjq7XsFUdCdZIAQ
cPHK6tYAMGkigWtydOulSnqf5kN+O0BrVs1IW1LF0qQpxj98ZQY5cdPr031VEEMphUtx1ldm
ydAADfyj6ZVEcYvPwz9aGJhjaCA7pL/KV+byUPT9E4SqRvNl95uOKiX7JJapvlFZeZaQ+PbC
94Cdw18mOafy6yvzr7QRfKRs5X6DJ3hzkc93sMkC1YHdXuKjbEvaCd4s96Bgdg76id0s92KO
LCmmTvDmIh+VXiFb5HuCv1zuveIo6GZaCLiUiPnDHs7Re+XeyE9mjk/U63wj2tmkgUD2jHqF
uTyaXZ1Rf3xifVqoV3U1zi3v99OW2CIOi3yvMIpbfKLI12v8BcBi6TCKNUW+UVzINKEqFSVO
qB9jr1uLfFxHG4xZQsKKMTUu1Thb94fJNo9fufczbASzkuXAbi7y1Rgwyo7vPsGbVV8vNTt9
eoI3qz4rLfsJT/D2Mh9lu7xP8N77sElhyTYYHOCv1n38SqPgm2EhMUrJvtS+TbJc79sy3Tcw
b5nkQ+HXpEKNI+Eqfbi7xBexjY7apteniwJhZ0D/t2wZdol5i6uYP95vbzf5RMEOXe7FJG/D
7A5+VUzc6HB3mlCV5rdct8ro2jynzJfpvis7p49PEJJe/T/cAPym47SQnRuz/um6j/71VoK3
RhGSQwgLHpYLVPL3GBzW4pui5KTBAd5+FM5pg8MDvFklW+nZg9wTvLf9EbqUxpYss5zord9i
ra0YJr14T/DedQag0inb53qiV7RB1kHQCr+CPPhOrEIrUWZB3210FU6adbRFNoc2Ei5zfCIY
qIII+53LnJzukkVK+ZLPxzQf3+4bCJJqFZKWW5+4aIWwvLQQ/+t+e7vJxzdZFmnXrRH5/5NP
yzVuN3A5NfY+zQf8ARRR5KTmOjntIb6iLdr5DCry0+vDHcx3mvIYTc82YMxNRv50mfwfMjnU
0nrWWvgAbz6VxNI0+Tw/wXt1gUqxbLPmCd6r/6hB8QdV8iOe6M36T0tPtmgc2K2fzzhEcbJa
f4IXaAu6zIuId/ErzoPvxCv0gtalgX+HKEnvxl5oxYSFwmDgeZKOFLJWu2mUeTCZHC6FV/Bp
9Wp5Pqb51AIckeECvn9I+jbWNYY3yIN5Z36Fedyi449kquzbNRNzpZwe6FkSTjJUfnN8XMSB
WFdi6f5DTxs32oL7jaANjsanF8if+Nxb7KgrJVvm46Jf6bdG+m23OaSCPevRd6I3qz4umHxU
HNjNmk/9pZOt+R3gzavMFsb1WTejA731W2zoG4qWtVg/wHtVX+9FsiMwJ3iF6rscsYj38Cs4
g+/kGLRiHbthM5dKloxWbmuCQIb+1pN8pFToVn0zUJtCco38oiVGh30wkDDJpxYOAz0jfxtr
TTao1UUthKNBe37lZtzigy5JEX3pq2DMCidlxRIdy320zZjjE4keyiYKGNq8po/Gl+g+Hh2N
zxLqRITNbzv2f9OskJ0buvoVfj/G5xCxhCNSUhkc6L36T8kfbNmetAO8ubkAi2JWRB/gvess
rphqT7bwvNCbFWC0ZCYPH5/YzWe+5I99zh5XnegV3ZGX3YTxRn4laPCdQINeWtXovAOwyGpI
Fv7aikSQ8ZnvHJ/HmW+EnLicVdas0+GSM98+cjqc5ONiDnvtWEWp9qSxSl1kDNgHESf8CtC4
xQdjys5QmutaVzDZM19cMgM9VIBzfEIBCkcfbrTwVM4mnMwlwf1DAQ6MDqcJdaEaxlGqFbK1
2bjqVwF+VgF+g9Fhp6S59Qneq/miwAPJJrUTvLnTj1wiJW3wTvDWVRZuxXVm7js8wVu/Q5Ze
rCcndk7w1k8oTYv/mcnv8AAvUBSooy6/V3gG3wzPqBweJMoRnJa0Tl6Rd4P1smLxPk0nXLe1
aatMLvssxydmaFYIvmHT1ezyMEuThq4pSDT3+uUlkYOuJ0aC75WccYsPlNbFutWny1JygeKq
FYrvck79/ROEqt9pLBD/iHS7bM1vzQqNFN8soa6irvga+TawYZbQ3ATWr+L7CV6H4YWf3Hyd
4L3CL7qlJDsIfYA3C79W9JE9kXQ7DPDeVUYo0JLi+QTvFX4KxTT5HZ7gvcJP44Q5e5B4gFcI
v8sXV7yJX6EZfC80w4USdwrd14Vzc6m8pjRWaWA/N8mHCrfeoQpVF7NZZ9TJ9vR/jHeM3sOz
6wO+NzQwVxecXh742mmIv263t5t0ortNK7qmjDl1Sx8l2pJQOxmkKE4TqsRgzsd1OQKlQ+3W
zHcM0rOnCXUwNMGGfsNZssvPr5paoV/h9612h7WwJJvTTvDmUl/1HUVyyOgEby/1+Y8/b3gY
4L2lPtGSPPEK5F6tV6WkD3xO8F6tZ1iSLUlP6AqdN2zqe6Vl8J3sAi7IZBbVMDNsWSGBS9KL
bfTeneNDRbVbB7LwOUxX+FY8HbDjqMI3uz6RH6bqoqizQe4Hy0sqln+o8L2yMm7xCRnhG1yJ
jnClms7K6Cua4FgGzprThKpKdannu03gltZFa3ythxW+6RXqZKhNekwR5Vfod5J3gdD7LqND
saTF/AneXOFr8RxMFvge2M1qzwqkG1QO8N41llaoZtf4AO/VfA/XmGRD5AnerPmkYM8dsh3Y
BaqC2iBdgl9pGXwnu4CLC74YDlUUrcmqb1y0oho2nOCd4+MCrkeSKzfkanl76xXVvfG57uz6
MFZtER5bUZJpM7ymkQ9HkcX8ysq4xQeK+V3WfHVIGmdzv/2qFZ18WAehidOEakeVHsMPJpLs
hY+rvlz1zRLqTZ2IVRKF2tKdfP+Tqo+/wuYwOfCzItX632snaC4uk3W9E7xXiVIr1bKDJQd4
rxZVKJCe2z3AW1e5t0eEc9I35ABv/Q4bQbQxZG0tn+C9n7BqwZzOeUJXKNE6UqKvIA++E6ug
paO/dpDDqY6SHfE6ear0dy+Zy3rq+zQf35ZY71UMY0g6O1GyorqFZqOJktnlAevQgB+nzckw
Zb/dloysDidKXiket/hgQVc42shfHK51sv7hK6yLBsL6fZqPS+Tugrpaj4EsS45k+VVLGgEu
h74/PrFAECnKKugbhfRbrMBve+Eqwfc9NoLRmf3/1s/+DwAA///tXWFvHLkN/S/pZ6uUREpU
getHA/UWLYr+AvfiXANcnCL2AXf/vuTuaHx3ycgcrSwb7fpLYvvNerialZ4o8r1vrGcLeHIG
klwsxqL+Cp7M+7Sw0ZqDXMBTR7kguRSM3qwVPPU9lL28y9kqIr2Ap94h5+TYqh1RwSPOnqnB
/XA188A91grJea8agplkQY7GehO9aMTZs29wv8548GixjUiAIUMxJoqHSBT7vDk+h+545AOY
kjYqx1AwJtvxCw3JEjd06p6et+ud8QiPK17oRcqMHowOxHrRiKNnaCQhO+MRGodMWXYaoE7R
yWoeU4YcPW+y88MZA+SLfHCydv7kBFalxz52fiF/ry8kGMBZW4gqeC7rQ/mbYGV9C3gy6xOq
SWAXElTwZNanRcDGupgKnpxLQ2ecPE/QyYyvCBE2am9X8JBsX8PEAVdTCtxnSgGUgDEJKzUf
MqVB/cTY6CfujAddkWmJE3jhRyFaGd+Ipv5nGF9fPMr4QvAow5MxG8/R9aKXrjbE1ZRiVzwy
IWdQp2giEGph9CmAIYpF7X7i7oCSamFHH6NaEZuPaYf0E3vYmhEO54yQ9mNFGZ2QSzI2z+lV
F843iPO9joZgDI6jMRe0oieTv+xyNM4ZFTyX/CXZ/FhrqCt47jjLttRZFeFP2LnUD9UIzqjI
U8FT77BwcWrmYFSQPoFHJPyw4RuCqzEF7jOmwMDMBZEjeTP9G6HN3laQ7oxH9gIxM2hPZMZk
7PGUi0YkZPOmee/hjPHxEUn2D1HGyHrYkYY0AzWK2p6et+ud8ajQHBQqAMfDazALFA8YoBBa
3U3dAcm2KSU+au5pbaiV/o1ok252FfePEAQU/ochqZWQ7ZHrbQe60L9XFRDMMl0alXAreHJt
HzhiY49EBc8lfKoJWIxmxhU8dZRVcS8no2Z0BU99DyMVx8kbBQQX8Nw7zMnFDMY7XMAjKBK1
Mn6rKQXu8QjQUg1UaUIhz1SMXld60QiK1Cq46o6HgmdS4y7NYpo7TUaMD2OL8vXGIxSWhIwz
+5CMBYthCIUNx8Xgmeftemc8miDTPgahxyjDlM26K0M4bH7+gesICClGlduLarY9tb/4aFb+
zBPXEVBGNQoOwSc0zsPQWVVwYXxvQUAQHGYjaangycSPXbQaXVTwZOKXXYxsFxBU8Fzix1lN
6qztuyfwZOLHqtVgFRA8gafeIQbUNLfRgHYBDyAWMbWKrVYvCtxjDSAcIXCKTCkk2c1ZBfdG
rMM+N4uteuPBiEe7K09IwWgtOSZ3mVsNn93xMMeYMnvhfmT0Cgmd/Z5fdeQ2WoxxtaLYFY8w
hOLB5+yLLwWMRgV61Qgm67eY7M05AUUJRJPlFFIy6g7AGGrezvX1BpS1pd1DEiorzNws7t11
JHRhfq+qICirZzZ271TwZMrnnZEKnKDT83wBjJnICp5L90hd/Yx9CBU8l+4leVusJwoVPPcO
WU/kjRujCh6R52suv6sTBe501khF7XQJinqBWunRGEWZVmVfbzyEKlcCIao2ojXNN8QoJG2d
VB/OCCcJ0ZOlN0Qib2yzDmPkSrzfGp6nx+16Zzya5mPMJZBHVl2ZqWm+zaP3m3MCQo6IICth
zGD0NxqU5vOpYQ7cH5AKTOlZtXC+aPSm6VXIubC9tyAjmBxb2/gqeC7pizpFG+vlKngy8WPZ
JRmP/ip4LvErxUEyZiIreDLxy85YR3yCzs3xYdKZ0TbCFTyAVYSWOxyuJhS4z1RDbk5tARKV
DGwVWx5CYjO0FuHeeITEJoxqfFLQSCpGkdiWSUhnPNEBhAKeZGwgstklZIjayaa/8dPzdr0z
Hu2vQ2Hk6koTIZvd1PIQOZom6+sNSFgfMEatkQgZJ4tHt3J83SPEDMEXDAC+GHus5aquLOxb
Z30vIiPorWbyQ2zkh7WZzBYSZMdWk5oKnstFfXYYjHX9FTyZixbHeYeotYLnjnIJzhuzpAt2
6juoDSOy9zXe4AKeeodJNjne2LiwYEecN1OLG6xGGbjHtoBcYEK1w2VZ2Ixch4aIe/hjJ/Mm
NeiLB5364ArXSSV7MHYo4RBhN+GiDWG37nhkEpOZljxR8cayL7loiB8atzKQq03Grni86qbm
TBhSxIBWJcFBDnytXqbueAIVkrGPBFa5AbnoxY2KO+MBJ8MTomwYYikpGsVkVAb7f5GJ/h8p
CXrdJFqVBE/gySfPxa4tXMFziZ+KA7Kx/a+Cp44yU3CA3qiJsoDnUj/ZU8jW2b4BUfDcO6Ts
IGfjJ2UBj0hExlaXyeqXgXvcC8gRYM5Amiwt1iMIuWjEaXqzsbgvHtRpKQbhFrLry2jVlRmR
5/KZW4txbzxcZOCLCi9TNpJzvWgAuTjK8jzzvF3vjMc7nxATMBXInIwKZm7EHNSWke6MRwWh
yUfdaJTI0Vi+4cdkipsy0t0DBBFTTkTq923W+e5jsxfy9/pKgt67QsaJf0VPP3wGo2XDgp3P
+oqxv6yC57K+hE6WEaP28QKey6kKOq3gMWYkT+C5d+jZpWT8oFTwCNbX7PVczSlwnzkFcY6y
vZeFiwNbvUNoSIoMWqyvNx4fijBYkKWY2aiNRWO8mMtmy8yhOx5VugnJ+0zInIyL8Bh5HGFJ
Lda3elPsikf1Z2OSfUYKqrhszPnpVQMCanoXdwckBMmXCJ5lbxftx88jeGxsCkj3BkQlFHXm
K/oJMi4V0DklXHjfm1ET9NGVZD4YX9Bz6R96h8VoFFnBcwmgCgRma4/xAp46zsUXWSKN9ZsV
PJdesUwmYFsYFuzU+2NVLQJjl3YFj6B/m6vXX1QcptIL2mlPUQqAD7J+ZWtMNCZJlqhRDNYZ
j7ZzFwLvoyxisVjp0ojPYNs7rnt8gDNFjAQUi1Hmn0adkDbEpGl1p9gVz7F/1WvbSfAIVi2j
3v7VrzqMt7LmN2cEJPy8qOqeMtpgrDof1GEcNvVFD+cElFWaKaaI8shlszzipefk/J6T2WqC
5NDYE79gJ5f36cNoLNup4MnlfSrRYXVYXMBTxzgGlQc05qoqeOp7GIUFW7POC3bu/QX5m2wk
zBU8osDPt+je6k1Be5wCgotAuiCoyRob6YRcNMQtrjQEZbrjoUjCJki4BLOx4ErbkkdkLzfp
+OGMeAKhihIf6/yMtRl60Qh2FBoCRrQ6U+yKR7NCnlUMO4dSkreSiRHp5RA3hfduzghIm/NV
ZpnUhCdPbTEOmyWyh3NGKAvbA5kRQkJ7iV/fFHehe29BSlDzYsaNSgVPru4LzmdrW8cCnsz7
ssNj/sIoJajgubyPZNlOxraJCp7M+9CRMZe7YOfeXyaXyfgUVvCIWrjUSrusphS0xyJAhpeL
1vJEL/zPKI4oF4055W2l+Xrjwaz9kaQWwWQ8sxjUZHzUON1chXvjIWQokCAUtDa2j5HKaUvL
0GpJsSselZZRRWx5bShClawtrC8vLdMfEBZ5qxLL4xzY7IIySEH6+SeuIyDZkKmOoI8xFjMz
v0hID+B9s4UEszNPkhU8OdHnHVv7pSp4eqLPG8WtF+zkNF+U1dobFWUW8GS6F1y2pmgqeHKi
L7psFjtcwEMIX2sBXi0paJ8lhSphqHsHEwdjQapeNITwNTp5u+NRf41QhPAxmIWwh0gJZtiq
ujycNTyJ9SukmIwqvnLRCCnBkBsiRrT6UeyKR/NBEPSRg3LUfHzRLNKuPF9vQJrnE+aKQS1j
7A4bY/J8WyN0OG+EGFLh5JOMk1X255LnG8H3XktKMBjLURfs5CxfcsWqd3bCTqZ87HI0UqoK
npzjY4dWq4sKnkz6ikNjkc+CnXt/nByycWtUwUMo39aOXtfg1YyCdpprQCkBvMqhZfPZIY44
282brvY358TDGDhmLNbCRL1kRIYPW4V8vdFQYdlXJz3FY2NVVXBpiIzgZp/N09N2vTMezdWp
+xBrVjlk4zQ5KMMXN+vebs4JiALJ4EhAR3uaNyMe3R8QB4rkJayUvNGW8E0V8sXfETnB/fql
PWAWfr5NCzdvKuE5NzXu79UB+f7z/fuPjx8/39/+eKUPwO3jQ+uX60A+3n754e7x6svt/Q93
V0Ixv9w9PHz37p//vrt79O6v8U/L//6mj867X7/ij5+/XD3It3ff/OHV3f3jl19++7jIA/X0
AJ0enU8f7z9++unT04+PL/Hduz8A3JZ4FG40v7j//Yuf3suvX/vD8WvXa39947c/f/vGP3wA
+TqO1Tffqz9uj8n54/X3dbz+cRmvCePV+OXDbz+s9QOvU8D7q7uf/6PjJvgH/cPLrPsgP7x9
/6AD+PTDf31+/8vTd+8/f//TJ4lYJoj7R/n3z/8FUEsHCGCxhN8UsQMAmJlEAFBLAwQUAAgI
CADju0NSAAAAAAAAAAAAAAAADAAAAHNldHRpbmdzLnhtbO1aW3PaOhB+P78iw+sZijFJWpiE
jiHcWiBgm5vfZFtgJbLksWQM+fWVDWQSavdQsDPtzMlDwLb07Wq12v12zd3XjYuv1tBniJL7
QvmTVLiCxKI2Iqv7wkRvF78Uvtb/uaPLJbJgzaZW4ELCiwxyLoawKzGdsJpFyRKJCYFPahQw
xGoEuJDVuFWjHiSHabW3o2uxsN2dDUbk+b7gcO7VSqUwDD+FlU/UX5XK1Wq1FD89DKWUvg6M
sHeaxYNlSbou7a5fR8dXpyq2X2Ws2P77G9PIhfrBDofl1+/2a9l9FBGHbmSbq/3tSNh9Qahc
WyMYvlqtkDTv/ZwpYsjEUPEh0KlXODzkW088RIQX6tJd6WeQ3wLuwyXPB3mGbO4kQV9/kW4/
XwzfhWjlJKp+U5Xkm8qpAoou8IqI2HAD7WNhMEzepniOcBl/e4rKMOzZR3oy7gsfKNQjjyj/
lqYR6JGeOhAm+S9F30/RHAh5+QQXbAY+o/6IMsTFCZgnmvu8rXyPvEhCrlyfbJv32F3qoxdK
OMCahxEfUBseb4BD/Qu8HPocWXmhH2l/MFGWp/St/jngKxZHaxijq4CsUswjnwd+0DfjyHWA
VdPCyoW42UbwA2qDck7dDIENSl1doGTq0RHoFODgGDVWtCydawOwglF0/SX67ZngmkPDjo+O
A7dJKYaAFOrcD+CZh4NYwpjQ1uGGPwpqscQ07MMVsLZpspYAsxRhCTffJqe0x3EWOfUcx/kl
JYHtEsnFcc7yKcYm8FM5Q+Xz7ckZ/X+HTnPoSEBDcKfnkQ8j6nGGw50ixoA+jfVn2Z+eCH9I
eV7Q+Rz5CLVJMfUT3UW+rcjyzW0G25qDUbqACc0Dl6g07EJgi1IoFyFxIBGRJgf0HnsMuCgf
obZ1TYqZBo/zeyZCYo/vCvaAIwYhomOLRIEz1Z0uOGQ9phHg6VQFjMNjp8pCwA5YrGlXb+Um
QYVMOFdqaVGWP58Z7Y7hE+uLS+G1wLTRGrFU9TMCT1b+XNfZwSsbxLStoCI+Jegl3Uv/bp6z
r+uTBzDIT+/d7G4EPoi86XeaOC3XhCL4ux6GG8FzkMfbgvPkEOZiQQpDgOQvpi/M8AFiHgne
Thi0fykjwyCUcZT4kMSTa7TIkbh8CLHIkS3my1lGoryKthXy4LhtYAIGb68biAB/W6g/j7v/
liQbm+50C2YDPmkNB319ofypf+PydDx58brG7AZbLn7qTxsPelOSE4bOFGWgsNXrdUtRHC36
tMU/za0itdOWFpqyaZKGWPuNZMx7VVWeBsb8m7fYlsdjKeTDlbcWcrBJVMfu4LX5VB6blW+S
5bY9W/GezErDM+aD6mAsvssbtpireDQzHLM7xE237Fiu7Zmu6gAyfbE7ZYEzrg6aYdh/UNhA
iecIfBVbXZWO9J4kdHkxO1PZmIVV8Tw0OsazMTe8hTw5yIjH22Lthi6FTdwYq63hWuiHYSvS
sfV90mkTYzr0oDu5HetjRWn0lLFUHU5a7clcUqeT1qY9a1eHuqS2H8JGy543mDF3hqas4scn
b2S4i/s/kpUJwsHBRot7BypcJpfkZ74ayJ+y5l3aKp4Xpzv/AXDwAYkiS876cbSyT4GtinxB
BTfIYZOVgNMmwFaAAU91ogtpTV50RgNrqDuBaxKA8N/UH9lnu6G4SOkzdiCBPrKKo2a/eCbh
2AsZAQ/6bZ+6ibk1g11oOsAHlpAUkX4fsuioZd6A7CPyPPFs4aPpr5/ObJjm3VGKvHS6e6P+
SJqYsjxide4dkh77Dn0Sl1ujgFg8AAnv0LIQtNvlyGF1KIrIXKJSjz3sfwShCefNpWWlYFH+
x0fwGzWbgFjwjAiVWsWXfvpNRint1yr1H1BLBwivI3eXcwUAAO8iAABQSwMEFAAACAAA47tD
UkFRsCC1BQAAtQUAABgAAABUaHVtYm5haWxzL3RodW1ibmFpbC5wbmeJUE5HDQoaCgAAAA1J
SERSAAAA7QAAAQAIAwAAAGg+AVUAAABaUExURSQkJC0tLTY2Nj09PURERE5OTlNTU1xcXGNj
Y2tra3Nzc3t7e4ODg4uLi5OTk5ubm6SkpKqqqrOzs7u7u8PDw8vLy9TU1Nvb2+Pj4+vr6/Hx
8f7+/gAAAP///+z12t4AAAUWSURBVHja7dxpc+MoEAbgZCwQhyRuJLr////clpOZyW5t1Sie
qj3ilyQOPhr0ABLtL3rhZyov0EILLbTQQgsttND+W1rqv9n/cfyPtLu9/1v//Op6vYEY/1mt
W6p3rm9s+rFGaz8x2MF6O6wN/SU0Y2o3tvDifH1Jv4qU7vqardljWAZb3pyj1Tq6spysn/fd
2kTWub1a2+VJvKrVtXjeoiYdYprGsV9fxoqz3RtNUinHrl0haYvWpK6ELiWP4mOcD1bNUlgn
6uNKr69UXetjCoGnpsaut8D1spZC5LSaHJ0d1czXz8RDc7d5Xl9JkXeLGk6noLyv069jXdNk
vHUxiHZKk/clm/mSVvMxB7N+Wwrb+ur8Rl5vV7WKquUlh2kYw5Hzcn1uJ5KV344XmvjGZUpE
Stoq+wVtm/1QsoBjNO341mdqLcsKuza3xemjv4aNbm0aIxcZr6vahaTTlXfDKXC0/hPnbbIh
dLuFtK3JJRedK9LWwkv4dazpvPpsU+lmWzg6OQPk79IYL24UG9bslrl36/rubP6q+62s5Pf9
wHc1PnlNpg9l0CfL+PFzjx2XGxkfGnh7uNz5iO/djLTU957HpfBBL+pD0eqTRd9D7o/6e7y+
FvihAf0zWF0OlqCfvepL4Vohc/xLuiQb8JEHU5ZKK8zje+XvT6sPycePmnz4Ht4L/c7BjvxQ
okqyG1PpV7RJyfVaJ3XoNLfogiEllSAVaYLorhsnctwrZOQlenur3985r7+vxDrOVa7h5t79
g2aV7QOJ5jA3Zp3MfkE78spr5nXxXL0erGVDloocPvFtUd4Zmr3e9SJbgfZzf8nBurVNy3Qo
ye30uaENTd1KTi2JhPxyNutjV2NFaXsgTNKB5lK9tJLLyr5x1OeWrIjnTVJcK7mhyCW72Fil
RVKxeefJNrbtTDT4diYsRe0z70dtfGYwi2RAEm5b7UfOj82tm6eHlvLEeapzuaI957ZIJuBl
gM4pTefcynGfv+dXGCXispx2WSvuXdu8BEn6K6f8lk5tdzJYkhnObZP1/Nj3xHPwzGNa+Sog
s/Zr7b7Z3nVVh6qmhiXLeVvlkNdkzlZiYLWrbqpApuj7RLfd5Dy/acdUJWViard6qGJL9HmW
JnV9bG7H1LflgTDpfshB1wvavEn22sPOR5AlmSP9rHDmvp8P8kI+nxX5WC2UIh2V25Hlo+fZ
MrZt2+/VEs/L1vHg3PIeHhmmXbofb0eC/RZaaKGFFlpooYUWWmihhRZaaKGFFlpooYUWWmih
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
--------------4B194FF8F3EA3786FF9EAE1F
Content-Type: application/x-compressed-tar;
 name="brin-stress-test.tgz"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
 filename="brin-stress-test.tgz"

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
4sSJE/vk/y10LU4AkAEA
--------------4B194FF8F3EA3786FF9EAE1F
Content-Type: application/x-compressed-tar;
 name="brin-bench.tgz"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
 filename="brin-bench.tgz"

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
--------------4B194FF8F3EA3786FF9EAE1F--





^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/9] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 4e0c9be58c..4099e72001 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8191,7 +8191,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------0E72B707603BED22B4040825--





^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/9] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 1487710d59..33841e14f2 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8191,7 +8191,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------22A4B241170149838D4D1F8F
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210215.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210215.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/5] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 1f72562c60..ccf609e799 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -389,6 +389,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -410,6 +413,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -470,7 +528,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -480,51 +538,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 7e380d66ed..853727190c 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -385,7 +443,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -406,9 +464,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -425,12 +483,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -460,9 +518,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -470,30 +528,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 4b5d6a7213..a3bb3558ec 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+ 	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index fb0615463e..0c28137c8f 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 687509ba92..925b262b60 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8104,7 +8104,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8120,7 +8120,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.25.4


--c7tltgiw2u7hovas
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20200912.patch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/6] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 1f72562c60..ccf609e799 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -389,6 +389,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -410,6 +413,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -470,7 +528,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -480,51 +538,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 7e380d66ed..853727190c 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -385,7 +443,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -406,9 +464,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -425,12 +483,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -460,9 +518,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -470,30 +528,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 4b5d6a7213..b233558310 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index fb0615463e..0c28137c8f 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 96d7efd427..2d013d4221 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8107,7 +8107,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8123,7 +8123,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.25.4


--oygwhy5yjes6547y
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20200917.patch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/6] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 1f72562c60..ccf609e799 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -389,6 +389,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -410,6 +413,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -470,7 +528,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -480,51 +538,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 7e380d66ed..853727190c 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -385,7 +443,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -406,9 +464,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -425,12 +483,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -460,9 +518,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -470,30 +528,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 4b5d6a7213..b233558310 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index fb0615463e..0c28137c8f 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 96d7efd427..2d013d4221 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8107,7 +8107,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8123,7 +8123,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.25.4


--5fmiyix6rzr5abmj
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename="0002-Move-IS-NOT-NULL-handling-from-BRIN-suppor-20200917b.patch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/7] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 1f72562c60..ccf609e799 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -389,6 +389,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -410,6 +413,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -470,7 +528,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -480,51 +538,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 7e380d66ed..853727190c 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -385,7 +443,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -406,9 +464,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -425,12 +483,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -460,9 +518,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -470,30 +528,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 4b5d6a7213..b233558310 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index fb0615463e..0c28137c8f 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index d9770bbadd..8f0f76601b 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8123,7 +8123,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8139,7 +8139,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--zzslo7zt7tqdcawh
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20201103.patch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 1f72562c60..ccf609e799 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -389,6 +389,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -410,6 +413,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -470,7 +528,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -480,51 +538,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 7e380d66ed..853727190c 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -385,7 +443,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -406,9 +464,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -425,12 +483,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -460,9 +518,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -470,30 +528,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 4b5d6a7213..b233558310 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index fb0615463e..0c28137c8f 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index c01da4bf01..bcbbc97de0 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8137,7 +8137,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8153,7 +8153,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------90362739C57C6315B5637FAD
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20201107.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20201107.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 1f72562c60..ccf609e799 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -389,6 +389,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -410,6 +413,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -470,7 +528,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -480,51 +538,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 7e380d66ed..853727190c 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -385,7 +443,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -406,9 +464,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -425,12 +483,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -460,9 +518,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -470,30 +528,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 4b5d6a7213..b233558310 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index fb0615463e..0c28137c8f 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index c01da4bf01..bcbbc97de0 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8137,7 +8137,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8153,7 +8153,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------291E0481B4400C0ECC8E497A
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20201108.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20201108.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 58fe109d2d..8a1a9da78f 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -389,6 +389,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -410,6 +413,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -470,7 +528,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -480,51 +538,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index d7b55f57ea..871e024e00 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8143,7 +8143,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8159,7 +8159,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------CF71AF65F7C337C37C24B045
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210112.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210112.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/6] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 58fe109d2d..8a1a9da78f 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -389,6 +389,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -410,6 +413,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -470,7 +528,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -480,51 +538,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index d7b55f57ea..871e024e00 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8143,7 +8143,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8159,7 +8159,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------D21F32E0F9E7408E9BE1AF2E
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210114.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210114.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/6] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index d27336adcd..f3ead7d53d 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8145,7 +8145,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8161,7 +8161,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------310A2AE1CC4C2E2E77559E3D
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-suppo-20210114-2.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-suppo-20210114-2.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index b5f52d4e4a..2ef11245a8 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8183,7 +8183,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8199,7 +8199,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------FA974B75A0C3E9CA18CE7207
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210122.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210122.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/6] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 158 ++++++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 140 ++++++++++++++------
 src/backend/access/brin/brin_minmax.c    |  92 ++++++++++---
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 303 insertions(+), 95 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..963b7079cf 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,78 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of
+					 * multiple scan keys. We can determine that based on the
+					 * number of arguments - functions with extra parameter
+					 * (number of scan keys) do support this, otherwise we
+					 * have to simply pass the scan keys one by one, as
+					 * before.
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same
+						 * for all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet
+						 * the criteria for a single one of them is enough to
+						 * discard the range as a whole, so break out of the
+						 * loop as soon as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+
+							/* mismatching key, no need to look further  */
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..a260074c91 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -251,6 +253,10 @@ brin_inclusion_add_value(PG_FUNCTION_ARGS)
 /*
  * BRIN inclusion consistent function
  *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
+ *
  * All of the strategies are optional.
  */
 Datum
@@ -258,24 +264,31 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/* Handle IS NULL/IS NOT NULL tests */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -284,7 +297,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -293,7 +311,14 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
@@ -301,10 +326,45 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all regular scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* Skip IS NULL/IS NOT NULL keys (already handled above). */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
+	/* This should be called only for regular keys, not for IS [NOT] NULL. */
+	Assert(!(key->sk_flags & SK_ISNULL));
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +384,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +444,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +464,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +483,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +518,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +528,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..e116084a02 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -140,29 +142,41 @@ brin_minmax_add_value(PG_FUNCTION_ARGS)
  * Given an index tuple corresponding to a certain page range and a scan key,
  * return whether the scan key is consistent with the index tuple's min/max
  * values.  Return true if so, false otherwise.
+ *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
  */
 Datum
 brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
 	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -171,7 +185,12 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -180,13 +199,52 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
+	}
+
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
+
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +287,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 1487710d59..33841e14f2 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8191,7 +8191,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------6A37408A2C42B5B56C3B3D49
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210303.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210303.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c          | 158 +++++++++++++++++++-----
 src/backend/access/brin/brin_validate.c |   4 +-
 2 files changed, 126 insertions(+), 36 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..963b7079cf 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,78 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of
+					 * multiple scan keys. We can determine that based on the
+					 * number of arguments - functions with extra parameter
+					 * (number of scan keys) do support this, otherwise we
+					 * have to simply pass the scan keys one by one, as
+					 * before.
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same
+						 * for all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet
+						 * the criteria for a single one of them is enough to
+						 * discard the range as a whole, so break out of the
+						 * loop as soon as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+
+							/* mismatching key, no need to look further  */
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-- 
2.26.2


--------------AC3FFB734F56C5F52D422EFC
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Process-all-scan-keys-in-existing-BRIN-opcl-20210305.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Process-all-scan-keys-in-existing-BRIN-opcl-20210305.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c          | 158 +++++++++++++++++++-----
 src/backend/access/brin/brin_validate.c |   4 +-
 2 files changed, 126 insertions(+), 36 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..f9a0476024 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,78 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any scan keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of
+					 * multiple scan keys. We can determine that based on the
+					 * number of arguments - functions with extra parameter
+					 * (number of scan keys) do support this, otherwise we
+					 * have to simply pass the scan keys one by one, as
+					 * before.
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same
+						 * for all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet
+						 * the criteria for a single one of them is enough to
+						 * discard the range as a whole, so break out of the
+						 * loop as soon as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+
+							/* mismatching key, no need to look further  */
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-- 
2.26.2


--------------82D677E9F94AC7574E460205
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Process-all-scan-keys-in-existing-BRIN-opcl-20210308.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Process-all-scan-keys-in-existing-BRIN-opcl-20210308.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c          | 158 +++++++++++++++++++-----
 src/backend/access/brin/brin_validate.c |   4 +-
 2 files changed, 126 insertions(+), 36 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..f9a0476024 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,78 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any scan keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of
+					 * multiple scan keys. We can determine that based on the
+					 * number of arguments - functions with extra parameter
+					 * (number of scan keys) do support this, otherwise we
+					 * have to simply pass the scan keys one by one, as
+					 * before.
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same
+						 * for all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet
+						 * the criteria for a single one of them is enough to
+						 * discard the range as a whole, so break out of the
+						 * loop as soon as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+
+							/* mismatching key, no need to look further  */
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-- 
2.26.2


--------------556A1DC61262AF15641DB204
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Process-all-scan-keys-in-existing-BRIN-opc-20210308b.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Process-all-scan-keys-in-existing-BRIN-opc-20210308b.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow future opclases to benefit from seeing all keys at once.

This does break existing BRIN opclasses, because the signature of the
consistent function changed. We might support both variants (with 3 and
4 parameters), but that seems pointless - the changes to NULL handling
likely require updates too. So better to make the failure clear. Also,
we're not aware of any out-of-core opclasses - there may be some, but
probably not many.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 doc/src/sgml/brin.sgml                   |   8 +-
 src/backend/access/brin/brin.c           | 118 +++++++++++++------
 src/backend/access/brin/brin_inclusion.c | 140 ++++++++++++++++-------
 src/backend/access/brin/brin_minmax.c    |  92 ++++++++++++---
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 6 files changed, 269 insertions(+), 97 deletions(-)

diff --git a/doc/src/sgml/brin.sgml b/doc/src/sgml/brin.sgml
index 06880c0f7b..078f51bb55 100644
--- a/doc/src/sgml/brin.sgml
+++ b/doc/src/sgml/brin.sgml
@@ -464,12 +464,14 @@ typedef struct BrinOpcInfo
 
    <varlistentry>
     <term><function>bool consistent(BrinDesc *bdesc, BrinValues *column,
-       ScanKey key)</function></term>
+       ScanKey *keys, int nkeys)</function></term>
     <listitem>
      <para>
-      Returns whether the ScanKey is consistent with the given indexed
-      values for a range.
+      Returns whether all the ScanKey entries are consistent with the given
+      indexed values for a range.
       The attribute number to use is passed as part of the scan key.
+      Multiple scan keys for the same attribute may be passed at once, the
+      number of entries is determined by the <literal>nkeys</literal> parameter.
      </para>
     </listitem>
    </varlistentry>
diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..743f2a925a 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,40 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
+					Oid			collation;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
-
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
-
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					/* skip attributes without any scan keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
+
+					bval = &dtup->bt_columns[attno - 1];
+
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * XXX We simply use the collation from the first key (it
+					 * has to be the same for all keys for the same attribue).
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
+					collation = keys[attno - 1][0]->sk_collation;
+
+					/* Check all keys at once */
+					add = FunctionCall4Coll(&consistentFn[attno - 1],
+											collation,
 											PointerGetDatum(bdesc),
 											PointerGetDatum(bval),
-											PointerGetDatum(key));
+											PointerGetDatum(keys[attno - 1]),
+											Int32GetDatum(nkeys[attno - 1]));
 					addrange = DatumGetBool(add);
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..a260074c91 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -251,6 +253,10 @@ brin_inclusion_add_value(PG_FUNCTION_ARGS)
 /*
  * BRIN inclusion consistent function
  *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
+ *
  * All of the strategies are optional.
  */
 Datum
@@ -258,24 +264,31 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/* Handle IS NULL/IS NOT NULL tests */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -284,7 +297,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -293,7 +311,14 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
@@ -301,10 +326,45 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all regular scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* Skip IS NULL/IS NOT NULL keys (already handled above). */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
+	/* This should be called only for regular keys, not for IS [NOT] NULL. */
+	Assert(!(key->sk_flags & SK_ISNULL));
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +384,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +444,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +464,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +483,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +518,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +528,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..e116084a02 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -140,29 +142,41 @@ brin_minmax_add_value(PG_FUNCTION_ARGS)
  * Given an index tuple corresponding to a certain page range and a scan key,
  * return whether the scan key is consistent with the index tuple's min/max
  * values.  Return true if so, false otherwise.
+ *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
  */
 Datum
 brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
 	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -171,7 +185,12 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -180,13 +199,52 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
+	}
+
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
+
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +287,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..2c4f9a3eff 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											4, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index c7619f8cd3..cd1eda38ab 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8223,7 +8223,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------D524CD37E77B36A2883A7617
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Move-IS-NOT-NULL-handling-from-BRIN-support-20210311.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Move-IS-NOT-NULL-handling-from-BRIN-support-20210311.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/9] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 4e0c9be58c..4099e72001 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8191,7 +8191,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------4B194FF8F3EA3786FF9EAE1F
Content-Type: application/vnd.oasis.opendocument.spreadsheet;
 name="brin-bench.ods"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
 filename="brin-bench.ods"

UEsDBBQAAAgAAOO7Q1KFbDmKLgAAAC4AAAAIAAAAbWltZXR5cGVhcHBsaWNhdGlvbi92bmQu
b2FzaXMub3BlbmRvY3VtZW50LnNwcmVhZHNoZWV0UEsDBBQAAAgAAOO7Q1IAAAAAAAAAAAAA
AAAcAAAAQ29uZmlndXJhdGlvbnMyL2FjY2VsZXJhdG9yL1BLAwQUAAAIAADju0NSAAAAAAAA
AAAAAAAAHwAAAENvbmZpZ3VyYXRpb25zMi9pbWFnZXMvQml0bWFwcy9QSwMEFAAACAAA47tD
UgAAAAAAAAAAAAAAABgAAABDb25maWd1cmF0aW9uczIvdG9vbGJhci9QSwMEFAAACAAA47tD
UgAAAAAAAAAAAAAAABgAAABDb25maWd1cmF0aW9uczIvZmxvYXRlci9QSwMEFAAACAAA47tD
UgAAAAAAAAAAAAAAABoAAABDb25maWd1cmF0aW9uczIvcG9wdXBtZW51L1BLAwQUAAAIAADj
u0NSAAAAAAAAAAAAAAAAGAAAAENvbmZpZ3VyYXRpb25zMi9tZW51YmFyL1BLAwQUAAAIAADj
u0NSAAAAAAAAAAAAAAAAGgAAAENvbmZpZ3VyYXRpb25zMi90b29scGFuZWwvUEsDBBQAAAgA
AOO7Q1IAAAAAAAAAAAAAAAAaAAAAQ29uZmlndXJhdGlvbnMyL3N0YXR1c2Jhci9QSwMEFAAA
CAAA47tDUgAAAAAAAAAAAAAAABwAAABDb25maWd1cmF0aW9uczIvcHJvZ3Jlc3NiYXIvUEsD
BBQACAgIAOO7Q1IAAAAAAAAAAAAAAAAMAAAAbWFuaWZlc3QucmRmzZPNboMwEITvPIVlzthA
LwUFcijKuWqfwDWGWAUv8poS3r6Ok1ZRpKrqn9TjrkYz3460m+1hHMiLsqjBVDRjKSXKSGi1
6Ss6uy65pds62ti2Kx+aHfFqg6WfKrp3bio5X5aFLTcMbM+zoih4mvM8T7wiwdU4cUgMxrSO
CAkejUJp9eR8GjnO4glmV1F066CQefcgPYvdOqmgsgphtlK9h7YgkYFAjQlMyoR0gxy6TkvF
M5bzUTnBoe3ix2C904OiPGDwK47P2N6IDKblXuC9sO5cg998lWh67mN6ddPF8d8jlGCcMu5P
6rs7ef/n/i7P/xnir7R2RGxAzqNn+pDntPIfVUevUEsHCLT3aNIFAQAAgwMAAFBLAwQUAAgI
CADju0NSAAAAAAAAAAAAAAAACAAAAG1ldGEueG1sjZJNb9QwEIbv/IrI9JqM87EfsbKuxIFT
EUgsErdV1p4Gg9de2U6z/HvyTVt64JZ555nxvJOp7m8XHT2h88qaA0kTSiI0wkplmgP5dvwY
78k9f1fZx0clkEkr2guaEF8w1FFfajxrnJT6QH6EcGUAXdclXZ5Y10BGaQ4NyDrU8ZPC7j2Z
K4biA2mdYbb2yjNTX9CzIJi9olmeYH9ZNo41xTetzK+3XkvLsoQxu6BSrNy1dXqkpADUOPT3
kCYpLKy1doWHKSa/i40Cpnilx+h/Lcy7G03M388WnhG+bHfwyqvRcYMGXR2s4w/q7PDzCMA2
KZJdkt09KNPeTt/329O2iJ4Bp6uzP1EEKOjdh1ZpGWcVvOpXScH6X4I8o1ka0yymxZFSlqeM
bpJyX+ab3S4vK1iwaR6UKvQnEcu279JPzr8c80/br3P3f7Ivi8RvodHz9BU9yxO7XpYPfQsf
lIhGPdRnjbGwrQn9tsgkCtR61TYZ3cy6PQ/ulwwlwCt4sVt46475H1BLBwhD5qoIhAEAAAUD
AABQSwMEFAAICAgA47tDUgAAAAAAAAAAAAAAAAoAAABzdHlsZXMueG1s7Vxtb9s4Ev5+v8Jw
cYsWWEXyWxJ7Exd71929Bdpg0XbvPhaMRMnclUSBouKkv/6GlKh3ybIiv6SoEzQVORzOPDMc
DimTN28fPXf0gFlIqH87nlwY4xH2TWoR37kd//n5V+16/Hb9jxtq28TEK4uakYd9roX8ycXh
CBr74SpgOIRCxCWPiPkrikISrnzk4XDFzRUNsK+arqptVrLbuNwMwxm/HW84D1a6vt1uL7az
C8oc/fNHXdRpHD9yPaXeIMa7dimJ832FD07XtkCqmdQLQN57F+eZWAxtu3IRtABsvjkLMm1F
ixhoqfHUMBY6wwFlXFEL5bt2JmgL2gqTddZXEOdbe5ijro0Fbb7to0v8v+tsOlkul7qsTUk3
3HObSUWtIrVpV3keQ1ezaYP9qN2VDbWh3TS1u5mKGUTMlUJapo5dLJqE+uRikrqpwyyrVisw
8UyHdogj7YHg7atUKkpb3GKux8+ZD86s7j44swoDDrlm5lXMSce4TSPfisdnzA8/BpgRUYVc
2WxV4FAeFK0qTAxd0KS2JNhVGqSkdd0CU80LNeJzzGiwyrUu2lS0725X2VuuPUf33YeKJM63
9iPvHrPO9gDbV0YbqLlttf+WEUAgR262kgsTFZRr96+lLolUC5f2cJAE1RyHQjhBfNMwzK/1
D1Ap//nwPhvszOuKqKAtBD6TkaBz2IypC85MvYaxO9GBQsMPYsCPR4nGucl0Ol6rmdOmMGva
yMSahU03XN/ENk+LR/GzkOx2/DMjCOIcTDqKwCPukyrX2xu/J+B90iyjT8gPa9j8gAIa/lSi
iwvHowJrQa852AezgoOFWxKGBYqAcBPs+IBAMOEwO0R7h/9C/43axcrRdBHpKeTYe5ZMjBJL
djd6hx+Qjxxo2CxdHfVR5HxP/OhxJI3GiY9Hv7UYtkQ5mHx6kzMn5XFWqPSwsI0iN8kVFedE
UhlfNBO77liRB4ghh6FgowUQ2oXskGDGVUANXGigWSTkyBeh3bhYED/DTCQ71XZSzoZRYdOV
i3wnQg7UYl8WmBDROAPx/vw0LrPQIHIgv+zDkkbxUSRfN6omYagq/n1XZSuyEhc/tjNOiTak
zDqt+v1OmqgG+/VNPCUlM1PBIDE6d8a4RDRKnjziy9nWgXYWcQgPIbDJjmp4pjw4zAJ13Uym
k6wjYB1xsFXymOSnLvUdwV9xAsOuV2lv8lHVhdikvtXEQK/I0kE8SO8UDYt8E3GsUV+jENNt
V0zJNnJDnKmwoRELuwl7jtrOjmMMVQbBgnjI1QIXQkfZj2oEb3bXyXSeiR6aBCZgAhFIK/pu
tb9RnIgIp66pbHX5fC0kOtQXy+Bcdcw5rZEZ6gOCrH+m6iAvMbGVNQ6JAzEB/AzvHE9mxBgs
y59qsTDAbf8wVFx4oC6EOYG95KzELsY6xTYX72r6evLuqas3BIYyfkYbuEZHcB1Go0BuPShY
8q42KnmeXotOd9B6gCM7fl0/As4XuDclgWMoPBSkc4lvkXj3Blw2wq/f/ODwn25Tn0JB4CYw
aiWv059thtl33+0B2j7g1KdIMt9xKSxUX9m2AZ+yyN/dPHPQ57v54vRuPm0zwfQc3XxxHiH6
CMAdyHcXg/ju5Xff7QHaiwvRL9fNLzu5uSWWcw3Wuurhyh4s4jclBfV6i1joqRvhE0apfRqW
eJkanTS77qFZVVytYVUrIBjlaiKx5KmzfAMDoW9/3Zan062fxDOjr58dFuTGPQIQedJD5INs
jJQDdPKAPC3wem6BgHp9loHns+9zeHz2WmoMjU9Pmecv2qYtSreFlj7J8pGnsA7eOrjr1ES7
+E8TjlcDZrvtCdcJ9x3yEHTF5XQJ7clhPEzeKl1t195vu1GWR3PWE67A+uByrs76YhdZ0tWe
5azzQbZ6Y/SUv+SekhqbuK4mvuuHTI5ZRlMqP5vQMpzTA76Ts8P3RYX1Z2E/PU/stb0cTAbB
JhX77sY2pHqyLwhGHPt8x6DoFsJ2RLB5spPfgZnbhdmkG7NdgVW6Tj7tT03Qda9xPmTKWt08
/Lbiar/tXIB4gNg6LMQvMrT2hn+A8HoA+Buja4OebfG1zx70WcXXqyHj69Vg8fVqZ3xtndoX
kxeXtr6otRrg+y2lrSdY4D0L+3NNW488r1VW90OlzYs+70/OKazL+DdUWJeDfZCwLl33WWnz
4rDfyfm24nq/vA0g/obS5hOG9t7wn2nafK7Rff+0fdH7S2rnEt8XQ8b3xWDxfdEc3+N2VXu8
i4+9pKdsmk8bZUXVY0OMxufSNeTKr+j71MfpKBKUJvhdUndPOade80Gk3EsEQ34qJ4DS435A
WnPar+kcUt15sIwyOd+V0PY9F6baN50OU/XpGbHm001VZZKuShTZEaYdpv4PRuKSghZTJzUB
YumNBVrRTfYwmjJOSL4Cg+k84LkywUS4CfPydtxi4my4cBHX2luvL1PjSzpzWiSEMPekFShG
k166K9x66z653kP3pLyP9tN27acn0n56QO0/gzTPcmi9mfcd5bgXbylUe9gEve+R+bfIbHxL
y16a2rZpZlZEDvUhcN67GmfFoJrWcahO6wRXyixxlN64uIIRNwqpS6zRq2tD/HSKuTP5qRjR
OKARf6WU+8OA3axXAkEXvQiHqcocYGg+gRzxXR0HVEyMOYz3MliOJ7iflBErGukxDSRbYolL
CFDEaQNFk1B9IfwEeUUUHmqE/0ap1Yt3IlafMW6acox3S38uL2vi6SGH4h2OOMulHUcCJQl8
XUBZLo8Oyr/Q0b1EwNERENOsnXUPCcj/EPP7ZpJlUM5KsV8Yo+z4EUF9VWonJLb8PAuS/XLr
n00TND3NkuHgarWsGGKCnguGBLQ+vpAgcSRf2Hd4ZLA1LDUS2PqtNJ4B2x757Ulhm7XCNjs2
bJb8dFfkIw7b94qOHQ1Upn6chDYvVHvc0UvX+ySPoh8PcWJqqkLh5WAN3IFGvID3h8CbjGuI
au7tISyEYkESb/7djsV+KPGjdFUlLkCDSVvzqAWsXabx+2zAbGCVn72iK5TZsDqDP0VbiR3j
TQKBcTFdLmYkvhDIQ8yBOhfboqZYyBL6Ymm8HyjYGMvreXxFkd4sVSLOKSTlNKgVsyiSXjFX
BzNPu5n5xdgwvxUxvZgvs62I3EAKkBXfmgrNjKuJalaTIRniJ4UoR0E8gKviMBV1X4ZHnSto
A/j3rJt/Q+zSxGWEiMv3f0kLRiDgUkayG3PFDa8MEV6D5fJ6tmxyzmpdYquLq/l1vb1UTV4U
qUJiJw4jsHsMDk0EMyKnYjoz/tkWmfMdAh9xEW84Sm7DDUf0/i9sQsFXzKgm3w6F5xkHvsFY
rjdO5kmFh8KURTrFJ4WCU9v7t/zoqMkBYnDWNyJJWQXJ33CDcUy9fvv27Y1eLkxKgpIpSoAL
7IrJqbq7TS+aK+39D6FL8pA5/Xqi+suVVURQrAqgt4qgV3DcBe3H5CLoFmSnFWTjJ4Yd8TZT
CLQv2HGBvn4d/48T7uZJ4+c3FUAKPRaKpP+WpBAnNBVS4ibkfKZ9B6uvlCgODjCdGNOJZkw1
Yz5eG4Yufw0jkUIQrn8cKYG93azlOduEtWGsplerxfLicnYpDj9Pr0UXK/mbKl3nhkX9Tueb
ymJ6voH8DsJ6ucw3iMtO4stCn0/i+cvC/vJJuFvDxkVGWKSqdf9Zyf13YLyvNToR7Y+UXh9n
9fob99f/B1BLBwgikX6e1QoAALFfAABQSwMEFAAICAgA47tDUgAAAAAAAAAAAAAAAAsAAABj
b250ZW50LnhtbOzdXa+byBkH8Pt+Cssr9Y7Y+AWDm2RVadXeJFXVbKverYaZZ2w2GCzAxyf7
6TuDDcav+2yOzzmZ9J+LJIYZGGD4Mdj87bc/Pq7S3gMVZZJn7/r+m2G/R5nMVZIt3vX//fPf
vLD/4/s/vc21TiTNVS43K8oqT+ZZZf7tmdpZOV8XVJpXoqoXsimyeS7KpJxnYkXlvJLzfE1Z
U3d+Xmder3c3XZbluHrXX1bVej4YbLfbN9vxm7xYDH7+18DO8yp6rAZN6UWhVHqp9Gg4HA8W
AyUq4T0ktP2hqfG4rFYXa/hRFA3quW3RMrmyaH/w348fPsklrYSXZGUlMkntBixFUXH3Ql24
u/nlw4Jb1xQ1x2G1NrswTqm7EFWILXcptqw52N3qxfpwAGyN3cFvtn06KGidF1VT2h4P7sps
2aOtrb6kxN5eW7hbe0WV4Fa2Zbt1H9Mk+3y9G9i5TVGdc1fyWKaezq8clFxzF5NrU2/UHkzZ
NnO9KdK6kUoOKCVbpRz4b/z2dMjz/MaRmwx2rw/dZKz43WSsuluj82L1uK/crmi/BHpcU5HY
yiI1TTIVvFxpc6JUVOTr+WEBR+e9SOWhJxWL1hqdbzK1Y+LC4m21+dESTk+Em/vEHw5smXar
EkoVb6tyb1WebpKtfXzIbX3+Ya/X1qlfiZh/etSFu7WzzSqmgn2AjZRnZ5jZzO3NDrUtErMH
OsXlzeL2EB1t3O0OGw3qQk2NNP+KDrLfq50lHBEiquUVBcLBRzOz/uvjh2635+7R0x5eyiJZ
s6nclT7qzPnq6uXInmP0YD1ogbOrL69UGA12sw9XOvX7V7p+b78vO8OFUf99MzbYNbgctBO0
GSN4WkjyFMm0fP92173ayb3da7sT3vX/WiTCXHjNNa0psErSL830we3KHxLT0ese0PsksvLC
Yv4s1nn5l5Nyu4n93tGibXlvQZnpQaYvl9ukLI9KrJNKmi7zIEzDbN/8nab9RL+K/2xuN6tT
htOkL2VFqye1qcgTVa+u9xM9iEwsTMXrrbtU+kXa+SHJNo+9+qBVSUa9v984sCcl79a+wbXO
vJ8uNlVuEEmkVy+n7eX130dbI3O/Xdm+8bVuZriQblZZv6nZneitzdXFbhOVPZ3P44LEZy8m
c+6aBdpVN0vcF98mynpmhgT+eJJk9QZ02nO9ccW1xhX59qRlZkq3WbtZduKSksXS+DZ840f+
zKz9dpM3JXn5ukpWIvW61atiQ3+k4aM7NtwMCIIXa/j4ng33w+irG65FWv6Bllficl9pJq7M
OIIKby0W5O1q/NP895Od98tU//JpSVT5J5vY2bzdOEYl5ToVX/Z7db9kO9ow9yreKldmqWnh
VfF5s3fDnv3oxztv/j8m/ZNCvf0rc2bX+8asWJK5dJqetRswrJLMuzBzX83OtQPBhVmdShZJ
Zeb67dxFkW/W9d102z8utLBtkb1DutRofzjsHxfa34J3Fnioe0MhuqYQpWkzZy0Ke5Nfv/Ca
65gWm7Q6VcpUOu+adTtEmiwyr8w3hR0BP4h0Q171Zd0eS3MTSaLdiqYT2g68LcS67qd2iJHl
nn3d1FJJQXI3J62Kdln57n0ET2QLO2Aens+wrbFLy9oGlMvC3OR5Ve7p5LD+3bwHuz1msNrU
i/PKMN90h3bur5uySvSX/VnWXs3M7hML0+hld9fU72vsds1xNbvJK1EsTC9KSduz2Z7Ilzq8
PaMOa6kXdXx9MFeB3Az4fxjWf/rdw5FvKnNPSyfbWc+y071qafrpYunt78i7O+q8kD2Ox2Xq
y+PRSM40p55YJr+Zib6/rjrTmpUUq33RXdddCmXvN85Wbsb3VNQtOGpes7jt3rFmeZ0m2bV7
ZqwtsqYN3Zl1/97PvVB5t9wbBewG13f7KT0ehrAna2/nX1l/O/96C06LsKmWdOXqeJez3V5s
8sIcGm93ftgL0Wyyrnplnpoh40k3VIlY5Jk5a+LUq4rjo9zOq8zs4kIPuLcmh6bvzrnjxhwb
cyhbNP3sUPiO9BzWU+Xr4wrwCB59Hx5dGfQ+7+hDJ4//r8OOpi/vl0iZ6uPUx6n/Gqf+BEMR
zlDkdsMxNIFP8OlZfJq+qE8XzXm6R08Y6gAiDJ6A0zeKU/AknJqz1j4N1Z2/f1v5q26q8JYu
KAAFr0DB7LUowE3WdzS2AV7A6xXwCoEXPqwCVsDKBawiYPWyWN3aSuAFvIAXHy9/+Fp6XdXl
Hm9O3xbl7lQ8mwon7y1LyuogDbAAFq+BhT98pjuzyVd+MmanC/nZPj6dKa/psmEgScTPMPDB
52b43AywfZewPdNd3J1hmxnYJGADbIANsLFge64bvDvDFquhwJNOgA2wATYmbE+LqL4UbEr5
8XO8Bw/YABtg+y5he1oa94Vgm+qYQg3YABtgA2w82J4W630h2IJhTBFGbIANsAE2JmxPCy2/
HGwasAE2wAbYuLA9Le38Uu+xDWUsZoANsAE2wMaD7ZmS0veFbaYNbAFgA2yADbDxYHum3Ped
R2wjKUUI2AAbYANsPNjcSB5MpRICsAE2wAbYeLA5kTyYyliFCrABNsAG2FiwjZxIHtSwneMF
2AAbYANsF2FzInkwIynEFLABNsAG2HiwOZE8mMUyEmPABtgAG2DjweZE8iD0pcRzbIANsAE2
LmxOJA+mMT48AGyADbDxYXMieTAVsQzxfWyADbABNiZsTiQPBCmSSB4ANsAG2JiwOZE8iGfk
S4zYABtgA2xM2JxIHsQhjSTeYwNsgA2wMWFzInkghzRVeNwDsAE2wMaDbexE8iCQchwhBA/Y
ABtgY8LmRPIg0HIa4ef3ABtgA2xM2JxIHgRKTqIIsAE2wAbYeLA5kTyY+WbEhk9FARtgA2xM
2JxIHghfRfE5XoANsAE2wHYRNieSB2KqhMSPuQA2wAbYmLC5kTwIVSxHgA2wATbAxoPNieRB
MJN+hO9jA2yADbAxYXMieRCEchQhKwrYABtgY8LmRPIgiAAbYANsgI0N28SJ5EGkVRjjcQ/A
BtgAGxM2J5IH9eMeCMEDNsAG2JiwOZE8iIQKYiQPABtgA2xM2JxIHoixGbFpwAbYABtg48Hm
RPIgCKQfTQAbYANsgI0HmxPJAy1oQnhAF7ABNsDGhM2J5IGBbUw+YANsgA2w8WBzInlAgZ7S
OV6ADbABNsB2ETYnkgc01mPCF00CNsAG2JiwOZE80PUfwAbYABtgY8E2dSJ5YFRTGg/oAjbA
BtiYsDmRPNAxTQmPewA2wAbYmLA5kTzQwsCGn98DbIANsDFhcyJ5QFM9IdyKAjbABtiYsDmR
PKChHpEAbIANsAE2HmxOJA+IdKhxKwrYABtgY8LmRPKAtIENHx4ANsAG2JiwOZE80DEF+FQU
sAE2wMaFzY3kwURPCN+gC9gAG2BjwuZE8qD+8ABfNAnYABtg48EWOJE8IKEDjR9MBmyADbAx
YXMieUChnhKyooANsAE2JmxOJA/CQJLAc2yADbABNiZsTiQPwkhqgeQBYANsgI0JmxPJgynF
5m4UsAE2wAbYeLA5kTyY6pgifHgA2AAbYGPC5kTyYKpiFZ7jBdgAG2ADbBdhcyJ5YG5FARtg
A2yAjQ2bE8mDGclYTAEbYANsgI0HmxPJgzCUWiBSBdgAG2DjwTZzInkQjqQUM8AG2AAbYOPB
5kTyYBrHMsRzbIANsAE2JmxOJA+EUFLiiyYBG2ADbEzYnEgexL7SMgRsgA2wATYebE4kD+IR
DSWyooANsAE2JmxOJA/iiEYSz7EBNsAG2JiwOZE8CIQcR/hUFLABNsDGhM2J5EFAchLhVhSw
ATbAxoTNieRBoA1sMWADbIANsPFgcyJ5UD/ugV+pAmyADbDxYAudSB6IiRIxvo8NsAE2wMaE
zYnkgRiqMEbyALABNsDGhM2J5EE8Ulri5/cAG2ADbEzYnEgeiJGKYjzHBtgAG2BjwuZE8iAI
pB/h+9gAG2ADbEzYnEgeBCFgA2yADbDxYXMieUAzPSXcigI2wAbYmLA5kTwgpWd6BNgAG2AD
bDzYnEgeaEETwvexATbABtiYsDmRPNBaS43fPABsgA2w8WA7/AzxNw2bWZ1GCB6wATbAxoTN
ieSBGbHFgA2wATbAxoXNieSBiJVCCB6wATbAxoXNjeSBNLDhOTbABtgAGxM2J5IHIlRS4nEP
wAbYABsTNieSB1pohU9FARtgA2xc2JxIHkSBmsQBYANsgA2w8WBzInkQTQ1seI8NsAE2wMaE
zYnkgfTJjNkAG2ADbICNB5sbyQNfRxojNsAG2AAbC7bRoSN8y7BRqAPCbx4ANsAG2JiwOZE8
mEkZidcJwf8PAAD//+zdu20DORSG0Zash6VhORw++i9hx0o2sIMbLfYHTgVKhANyyI8XbGAD
WyBsEeVBu8/HCTawgQ1sRdgiyoPd5piGuYANbGArwhZRHlywzWkSPNjABrYibBnlwTFf01YU
bGADWxG2iPLggq1N5QHYwAa2ImwR5cHnoUnf2MAGNrAVYYsoD/b2gi7YwAa2OmwZ5cG5+rJi
AxvYwFaD7RZRHuw21/RsEdjABrYibBHlwedUVAQPNrCBrQhbRHlwwdbnG2xgAxvYarBllAdr
HxtsYAMb2IqwZZQHY53LqSjYwAa2ImwZ5cFYe/3GC2xgAxvY/oQtozxoe2ytKNjABrYibBHl
wXms+7BiAxvYwFaELaI8WL3dDt/YwAY2sBVhiygP1mi9ed0DbGADWw22e0R58FmxSarABjaw
FWGLKA+uFdu7fYENbGADWw22jPKgr9s0pQpsYANbEbaI8uD6taPfwQY2sIGtBltEebDaMQ4R
PNjABrYibBHlwerHPg6wgQ1sYKvBFlEeXCu2ftiKgg1sYCvCFlEe7L6+5m+8wAY2sIHtT9gi
yoPP0+C2omADG9iKsEWUB5/rHlZsYAMb2GqwPSLKg/0ae5h5ADawga0IW0R5sG/ns7ugCzaw
ga0IW0Z58Brn8I0NbGADWxG2jPJgtLO5oAs2sIGtCFtEebDHWmuCDWxgA1sNtojyYK/9NqUK
bGADWxW2iPLgM6XKe2xgAxvYirBllAf7WrO5xwY2sIGtCFtGebD3aUoV2MAGtipsEeVBf89z
iODBBjaw1WB7RpQH/XXBdgMb2MAGthpsGeXBNjAZbGADWx22iPKgPebjdEEXbGADWxG2iPKg
3eb99I0NbGADWxG2iPJgvtZaYAMb2MBWhC2iPHiP0butKNjABrYibBHlQbtfW9EH2MAGNrDV
YMsoD87VPA0ONrCBrQpbRnlwrvf6BhvYwAa2GmwR5cGeWlGwgQ1sZdi+I8qDfV60mXkANrCB
rQhbRnkw92O77gE2sIGtCFtEebDPdawX2MAGNrDVYIsoD+ZtjWlKFdjABrYibBnlwWPN9QU2
sIENbDXYIsqDPRwegA1sYKvDFlEeXKw9t/IAbGADWxG2jPLgZ0qVwwOwgQ1sRdgiyoPz69qJ
SqrABjawFWGLKA/GWH16QRdsYANbDbZXRHlw3q4Vm7miYAMb2IqwRZQHa/VHm2ADG9jAVoMt
ojy4fu3dTakCG9jAVoQtojxYs632BhvYwAa2GmwR5cG1FX3aioINbGCrwpZRHvy8oGvFBjaw
ga0IW0Z5cK6XF3TBBjawVWHLKA9+ni2yYgMb2MBWhC2iPNjP8Rxe9wAb2MBWhC2iPLh+rXdb
UbCBDWw12N4R5cFa/d4kVWADG9iKsKWUB9/tN15gAxvYwPYnbBHlwZ77bpgL2MAGtipsEeXB
BzZJFdjABrYibBHlwf4er+EFXbCBDWxF2DLKg/d8TNc9wAY2sBVhyygPHuc4XdAFG9jAVoQt
ozxY+9ieBgcb2MBWhC2iPOh7rmHFBjawga0IW0R50NscDg/ABjawFWE7IsqDPq8Vm/F7YAMb
2IqwRZQHe5sEDzawga0OW0R50M85hwgebGADWxG2jPKgzXM6FQUb2MBWhC2jPGhzzg42sIEN
bDXYMsqDYx7T4QHYwAa2ImwZ5cHazQVdsIENbFXYMsqDY3bf2MAGNrBVYYsoD3abwzc2sIEN
bFXYIsqDzzc21z3ABjaw1WBrEeXB5xtbAxvYwAa2GmwR5cE62+vYYAMb2MBWgy2iPFijjWYr
Cjawga0IW0R5cK3Y7ofDA7CBDWxF2CLKg2vFdjTDXMAGNrAVYcsoD/q6LzMPwAY2sBVhiygP
rq3o85hgAxvYwFaDLaI8uLairRmYDDawga0IW0R5sHr7OiRVYAMb2IqwZZQHe69tKwo2sIGt
BNvj3z/C/xm2/px9ODwAG9jAVoQtojzorws21z3ABjawFWGLKA/2sBUFG9jAVoctozyYbTWH
B2ADG9iKsGWUB6s/22+8wAY2sIHtT9gyyoNzvZeZB2ADG9iKsGWUB7PfmggebGD7j2H7BwAA
///s3bvN5TYQgNGWdPWiWI746r8Ey5s4sIMJPcDBFvAniwPyit9MXthylAfzvap5bGADG9iC
sOUoD0Yd1VUUbGADWxC2FOXBn6toAxvYwAa2EGy/FOXBB9tW7TwAG9jAFoQtRXnwHH28YAMb
2MAWhC1FefCcYAMb2MAWhy1FeXDNNmypAhvYwBaFLUV58Gy9vb6Kgg1sYAvClqI86H2+o4MN
bGADWwy2FOXBuOacxhaBDWxgC8KWojwY5xxgAxvYwBaFLUV5UEp/XhN0wQY2sAVhS1EelOeD
zYkNbGADWwy2PUV5UN5eX+v3wAY2sAVhS1Ee9HOW4bkH2MAGtiBsKcqD3uY7RPBgAxvYgrCl
KA/68I4NbGADWxy2FOVBOfpdbakCG9jAFoQtRXlQzl4scwEb2MAWhS1FeVB2JzawgQ1scdhy
lAd1rnmCDWxgA1sMthTlQX9nHbZUgQ1sYAvClqI86M8Hm0GTYAMb2GKwHSnKgzbmOSRVYAMb
2IKwpSgP7qf/rN8DG9jAFoUtRXlQ9n5VD3TBBjawBWFLUR7Me13Tcw+wgQ1sQdhSlAfzt47p
qyjYwAa2IGwpyoPvxHY6sYENbGCLwpaiPPhObLsTG9jABrYobCnKg9lWWZ57gA1sYAvClqI8
eEqfr3lsYAMb2IKwpSgPrtb647kH2MAGthhsZ4ryYO2rLg90wQY2sAVhS1EerHO9q4ANbGAD
Wwy2FOXBqGubF9jABjawxWBLUR6MuX7zARvYwAa2GGwpyoPRnNjABjawxWFLUR6Uq5e6wAY2
sIEtBluK8qDcvbwb2MAGNrDFYEtRHvQyn+E3NrCBDWxB2FKUB3OsZ+1gAxvYwBaDLUV5sOpo
dh6ADWxgC8J25SgPnlGG9XtgAxvYgrDlKA/67FMEDzawgS0IW5LyYC7v2MAGNrBFYUtRHsxu
HhvYwAa2OGwpyoPvKjqnsUVgAxvYgrClKA8+2AbYwAY2sEVhS1EejG328W+8wAY2sIHtP2FL
UR60dx5dKwo2sIEtCFuK8uDpY3vBBjawgS0IW4ryoG5jb5IqsIENbDHY7hTlwb23VT33ABvY
wBaELUV5cP/ABjawgS0OW4ry4D4+2FxFwQY2sAVhS1EelK1fVSsKNrCBLQhbivLgbv2oBk2C
DWxgC8KWojy4+webeWxgAxvYgrClKA/ut+/VwmSwgQ1sQdhSlAerzk1SBTawgS0KW4ryYNWx
xgAb2MAGthhsKcqDda22fDwAG9jAFoOtpCgP1lhzObGBDWxgC8KWojxY79yHCB5sYANbELYU
5cE61rt8FQUb2MAWhC1FeTDXetYBNrCBDWwx2FKUBx9rfb1gAxvYwBaDLUV5sO7VlvIAbGAD
WxC2FOXBs8avGVsENrCBLQhbivLgz6BJY4vABjawBWFLUR48Zx+v39jABjawBWFLUR48ta/X
XlGwgQ1sMdieFOXB8/QJNrCBDWxR2FKUB22fW/dVFGxgA1sQthTlQevzGBvYwAY2sMVgS1Ee
9GPe4wIb2MAGthhsKcqDe/Wz+ioKNrCBLQhbnvLAPDawgQ1sQdhSlAdrX++6wQY2sIEtBluK
8mDNv/+BDWxgA1sMthTlwaqme4ANbGCLw5aiPGjX/HWb4MEGNrDFYKspyoM/sCkPwAY2sAVh
S1Ee1D5KcxUFG9jAFoQtR3lwuoqCDWxgi8OWojyobdxNKwo2sIEtCFuK8qCM/r4n2MAGNrDF
YEtRHtQyzuaBLtjABrYgbCnKgz9XUR8PwAY2sAVhy1EePKOY7gE2sIEtCluO8qCMvS+wgQ1s
YIvBlqI8+GA7h/V7YAMb2EKwnf/8R/ifw3aNA2xgAxvYYrClKA9amXsfYAMb2MAWgy1FeTCf
5y5gAxvYwBaELUV58MF2FM89wAY2sAVhS1EezPq0x29sYAMb2IKwpSgPVp3bcBUFG9jAFoQt
RXkwS1lFUgU2sIEtCFuK8mDepRdXUbCBDWxB2FKUB9+JbRZJFdjABrYgbCnKg++vGVsENrCB
LQrbL0d5cPSt2XkANrCBLQhbivKgPuNqBWxgAxvYYrClKA9qBdv/Gba/AAAA///s3UuO5DYQ
RdEt6S9yOSIjYv9LcHZOPKhsOADbyBfoWwuo4YGSuo8CNmBTg63E8mBufnEfG7ABG7BlYSux
PIjHd9+ADdiADdhysNVYHlgszkWTwAZswJaErcTywCxW54wN2IAN2JKwlVgexPTp3O4BbMAG
bEnYSiwPLGJzPpgMbMAGbEnYaiwPRj8agS6wARuw5WDbSiwPXrCdjWuLgA3YgC0JW4nlQUze
igIbsAFbHrYSy4M45jp4YgM2YAO2JGwllgexju0BNmADNmBLwlZieTAOX+YANmADNmDLwVZj
eXDbOn/iBWzABmzA9hG2EsuDF2wbsAEbsAFbFrYSy4P3B5OBDdiADdiSsJVYHvjTrPGVKmAD
NmBLwlZjefA0b4zggQ3YgC0H215jedDaeTOpAjZgA7YkbCWWB95bbyuwARuwAVsOthLLg9cT
23HTsQEbsAFbErYSy4PHzCbfPAA2YAO2JGwllgdPszl3YAM2YAO2HGw1lge//ujYgA3YgC0J
W4nlgVuP3oAN2IAN2HKw1VgezN76AmzABmzAloOtxvJg9J2rwYEN2IAtC1uN5cHoWyP3ADZg
A7YcbEeJ5UF7ZnDRJLABG7BlYSuxPGj7nA8vD4AN2IAtCVuJ5YE1Dz+ADdiADdhysJVYHtw2
n4flAbABG7AlYSuxPLhjDmADNmADtixsJZYHtrk5HRuwARuwJWErsTyY4cN+4gVswAZswPYR
thLLg+kv2Mg9gA3YgC0JW4nlwd1nfzZgAzZgA7YcbCWWB9EtjEkVsAEbsOVgO0ssD2KJHrwV
BTZgA7YkbCWWB2/YCHSBDdiALQlbieVBPGHBCB7YgA3YkrCVWB7EHTM6sAEbsAFbDrYSy4Nm
tjwBbMAGbMCWg63E8qC5rYPlAbABG7AlYSuxPPAtdueMDdiADdiSsJVYHniPK3hiAzZgA7Yk
bCWWB3a5O98VBTZgA7YkbCWWB/c1787LA2ADNmDLwXbVWB50c+OMDdiADdiSsJVYHvgZh7MV
BTZgA7YkbCWWBzZj9RvYgA3YgC0HW4nlga0+uWgS2IAN2LKwlVgeWMTmfH4P2IAN2JKwfXF5
8OElQYTF/H8g+kzMf24JbMDGH8DGF7v+37BhsAEbsKHNxher+Y9sTJ42YAM21Nn4YpP+YQYd
to0VNmADNrTZ+GLx/U+3J8AGbMCGJBv3F3vqn2z0hacN2IANfTa+WCt/PNtwjkRhAzbU2fhi
C/zxbGPlaQM2YEOdjS+Wth9+pKyvHykbbMAGbGiz8cWO9TdnG7ABG7AhzoZaJTr+/iQSbMAG
bGiyoVaJjnhgAzZgQ5sNqUq0b7aPHTZgAza02ZCqRPvxYuOADdiADW02pCrRZ7E26DZgAza0
2WhSlegT5vOGDdiADW02pCrRvvMjBTZgQ58NqUq0n3aMEzZgAza02ZCqRN+bFIcN2IANbTa0
KtGwNrimBzZgQ5wNqUr0fbZBtwEbsCHOhlQlOhc/DTZgAzbE2ZCqROftzRpswAZsaLMhVYk+
l43JfRuwARvibEhVovcx786bFNiADW02ulQleu0jOvdtwAZsiLMhVYneJ08bsAEb+mxIVaLX
+nra4GwDNmBDnA2tStTjDOJy2IANcTakKtFoMbndCzZgQ50NqUo0LNbgq2ywARvibEhVonHE
E9y3ARuwIc6GViW6+2WcbcAGbIizIVWJzsNvu2ADNmBDmw2pSrRvtrGAhQ3Y0GbjXKQq0bA4
AjZgAzbE2ZCqRN9scJcobMCGOBtSlWh43MHZBmzAhjgbUpXoPDkShQ3Y0GdDqhKdjWt6YAM2
9NmQqkT7xQcPYAM29NmQqkSfbnPyJgU2YEOcDalK9NrnwjU9sAEb6mxIVaLRY8aADdiADW02
pCrROGMER6KwARvabKxSleh7k8KRKGzAhjgbUpXou9tgOA8bsCHOhlQlOi9vsAEbsKHOhlQl
+ix8Oho2YEOfDalK1A435+Zy2IANcTakKtEx/TDuEoUN2BBnQ6oSve/ZHtiADdgQZ0OrEm1z
7byAhQ3YEGdDqhK9fY4HNmADNsTZkKpE721e3WADNmBDmo1NqhJ9f8yRSwFhAzbE2ZCqRGOG
BU8bsAEb4mxoVaK/bvfqsAEbsKHNhlQlOsJP45oe2IANcTakKtF4/Vu+OA8bsKHOhlQlGsaR
KGzAhj4b/6oS/QsAAP//7N2JDR0hDADRlvZeKAds038J+dkeIk2kaeKJYzD/YLXRHdMjG7JB
ZwNViY4z+1yyIRuywWYDVYl+v7I5b0M2ZAPOBqoS/Y5EvYCVDdlgs3GiKtE56gw3KbIhG3A2
UJXouHOED+dlQzbgbKAq0dnqiJIN2ZANNhuoSnS8OcNf2WRDNuBs0CrRZz2yIRuywWaDVYnW
auZesiEbdDZQleic3qTIhmzw2WBVopc3KbIhG3w2UJXoaB6JyoZs8NmgVaLPcgSxbMgGm40L
VYmuXPvyVzbZkA04G6hK9Jvu5SZFNmQDzgarEp11+pmjbMgGnQ1UJfqN6fEFrGzIBpwNVCU6
ZmZ4JCobsgFnA1WJzrO2cASxbMgGnA1WJXrVHlM2ZEM22GygKtG1VizZkA3ZgLPBqkTPHI4g
lg3ZoLOBqkRHyzAulw3ZgLNxsyrRvw/nnVwuG7IBZwNVib53vN1NimzIBpwNVCXaRqyRsiEb
ssFmA1WJti4bsiEbfDZQlejd5mxewMqGbMDZQFWi9/tjw0pUNmQDzgaqEr27qw3ZkA0+G6hK
9B3Rh92GbMgGnA1UJfrdpJRsyIZssNlAVaLtjhyebciGbLDZeFCV6B0zmxewsiEbcDZQleid
PzbcpMiGbMDZQFWid8mGbMgGnw1UJfr2aN6kyIZs0NlAVaKtxRohG7IhG2w2WJVozWq+gJUN
2YCzwapEl2zIhmzw2UBVot8FrEeisiEbcDZQlejbog3/gJUN2YCzwapEM/fhJkU2ZIPNxouq
RFvkJhuyIRt0NliVaHPehmzIBp8NVCX6zujjlA3ZkA02G6hKtM3fJsWbFNmQDTgbqEr0rRjD
H+dlQzbgbKAq0XZEjCYbsiEbbDZQlWhveU9/ZZMN2YCzwapEp2N6ZEM2+GygKtFnm9U32ZAN
2WCzgapEnzu27gWsbMgGm42GqkTfiDEu2ZAN2WCzgapE/75JmW5SZEM24GywKtGwEpUN2eCz
wapE06dssiEbfDZQlei8agv/gJUN2YCzgapE5127bMiGbNDZQFWi480ZTveSDdmAs4GqRGfW
lbIhG7IBZwNVic5eZ/hwXjZkA84GqhJdubbyJkU2ZIPNRkdVojGqp0MBZUM24GygKtHY60nj
ctmQDTgbqEo0Zo30AlY2ZAPOBqoSHZEZDgWUDdmAs4GqROOsN2VDNmQDzgarEq268pAN2ZAN
NhuoSnT2Ouw2ZEM26GygKtGV61yuNmRDNuBssCrR97facASxbMgGnA1UJTr3XOE/KbIhG2g2
no1ViT71pv+kyIZswNlAVaKzuUmRDdngs8GrRH2TIhuyAWcDVYnG4ZsU2ZANPhuoSrS/ec1H
NmRDNthsoCrR/siGbMgGnw1UJdq7P87Lhmzw2UBVor9NimzIhmzg2UBVoh8bblJkQzbgbKAq
0T7ymV02ZEM20GzsqEq0R77TbkM2ZAPOBqoS7fO32pAN2ZANOBuoSrSnqw3ZkA0+G6hK9LuA
9QWsbMgGnA1WJTo9EpUN2eCzwapE+48NVxuyIRtwNlCVaB4V6WeOsiEbcDZQlWi06ukmRTZk
A84GqhL9rTayNtmQDdlgs4GqRFeuY+2yIRuygWbjQFWimWsvn7LJhmzA2UBVotlqldO9ZEM2
4GygKtF8qsrvlWRDNuBsoCrRXOsob1JkQzbgbKAq0QzPNmRDNvhsoCrR2lxtyIZs8NlgVaJz
beV0L9mQDTgbrEq0W4nKhmzw2WBVoqeVqGzIBp8NVCWa3W5DNmQDz8aJqkRXrK18ASsbsgFn
A1WJrlznOmVDNmSDzQaqEo2qmSkbsiEbbDZQlWgd66wpG7IhG2w2WJXo7ZsU2ZANPhusSnRf
R/nhgWzIBpwNViU61la3bMiGbLDZQFWidXq2IRuywWcDVYmutcZykyIbsgFnA1WJfj/O+0+K
bMgGm40LVYmOygrnbciGbMDZQFWizxt790hUNmQDzgarEo0a6ZGobMgGnA1UJbqiVpVsyIZs
sNlgVaJbRcqGbMgGnA1UJZq7X0fLhmzw2UBVouPIPl1tyIZswNlAVaJzzxXOEv1/2PgDAAD/
/+zdW27cRhCF4a14AzY4M7w0l9NdXRUEMCxD0f4RmgKiKNZDDWBgTsf/s2zIhjQfePkPCRu/
KRtSlei62mXnoYCwARvibEhVota9dYMN2IANaTYWrUq09268JwU2YEOcDa1K1Oy2c20DNmBD
nA2tSrR75SQFNmBDnQ2pSrRNPYwFLGzAhjgbUpXo+Z4Uug3YgA1xNqQqUQteeAAbsKHPhlQl
erLB0QZswIY4G1qV6OIX45IobMCGOBtSlej5dC+6DdiADXE2pCrR2no34nLYgA1tNlapSrS5
z/0CG7ABG9psSFWibfOLcScFNmBDnA2pSrRdfWI4Dxuwoc6GVCW67VYqJymwARvibEhVoktt
VrgBCxuwIc6GVCV6HG3s9QobsAEb2mxIVaJbt1q5AQsbsCHOhlQlukTzfYIN2IANbTakKtFl
b1Z4KxtswIY4G1KVaKl9qkzZYAM2tNnYpCrRsppXjjZgAzbE2ZCqRMtkrTJlgw3YEGdDqhI1
54UHsAEb+mxIVaJxuOFsUmADNsTZkKpE+3awcYMN2IANbTakKtHmvnQqUdiADXE2pCrRtvJQ
QNiADX02pCrR3XtpsAEbsCHOhlQlerJBtwEbsCHOhlQlultfW4UN2IANaTaKVCVaL31vxOWw
ARvibEhVonXutQVswAZsaLMhVYmeRxvkXrABG+JsSFWiu/eNS6KwARvqbGhVoh5XL7ABG7Ch
zYZUJeolVufaBmzAhjgbUpWo77ABG7Chz4ZUJXqcpFw4SYEN2FBnQ6oSDfNgOA8bsKHOhlQl
ej5vg00KbMCGNhu7VCXqLdbgZY6wARvibEhVor7F4sTlsAEb4mxIVaLH0cbG0QZswIY6G1KV
qM8xc20DNmBDnQ2pSjR6XIOHAsIGbIizoVWJ7rEG74CFDdgQZ0OrEl1joduADdhQZ0OqEnXj
kihswIY+G1KVqN+4JAobsKHPhlQl6h4leL0SbMCGNBvbJFWJxhR7LLABG7ChzYZWJVq5kwIb
sKHPhlYleomb88ID2IANcTa0KtEeG7kXbMCGOhtSlagvMdNtwAZsqLMhVYmGeecGLGzAhjob
epUow3nYgA1xNh5YiT49Hz+4z6+fqH/91D56xujk1v3to1//ePp2fOra188vz+9/I/752svx
5ecPflt+GUNv/4PXD+b7f8V7nN7+7PPrL+P0ZZu/v3z66+nrn/3Tfz6Rv9Cwt+/78vT9/V8A
NmD7X8P2wI71DtguB2wBbMAGbMCWg+2Bpe0dsF2BDdiADdjSsF0e2ALfAdvNu0/ABmzABmw5
2B5YK+dhK5O1ugEbsAEbsOVge2BPfSdsK7ABG7ABWw62Bxbfedisee0N2IAN2IAtB9sDm/Q7
YNt97zuwARuwAVsOtgdW83fAVg/YKrABG7ABWw62B3b9d8BWvHDEBmzABmxZ2IZYHmzBzQNg
AzZgy8M2xPJgc6t1ATZgAzZgy8E2xPLgPBUtwAZswAZsKdiuQywPbD1gI9AFNmADtiRsQywP
tn6cis7ABmzABmw52IZYHvTF3S/ABmzABmw52IZYHpywXYEN2IAN2HKwDbE86MXDORUFNmAD
tiRsQywPysWMp3sAG7ABWxa2IZYH5QpswAZswJaHbYjlwQkbHRuwARuwJWEbYnlgxmOLgA3Y
gC0P2xDLg82tMakCNmADtiRstzGWBz8eNMlji4AN2IAtCdsQywPb2IoCG7ABWx62IZYH56SK
U1FgAzZgS8I2xPLgfB4bsAEbsAFbErYhlgc+x+wGbMAGbMCWg22I5UEch2zBzQNgAzZgS8I2
xPLggK0F7zwANmADtiRsQywPIsLjZ7yADdiADdg+hG2I5UFZrFdORYEN2IAtCdsQy4OyW9QO
bMAGbMCWgm0eYnmwX/ut3YAN2IAN2HKwDbE8qEuvNgEbsAEbsOVgG2J50GfvvPMA2IAN2LKw
DbE8KLP1Su4BbMAGbEnYhlgelM288jw2YAM2YEvCNsTywMJb564osAEbsCVhG2J5YP2Aja0o
sAEbsCVhG2J5YM4RG7ABG7DlYRtieXCeiv6MF7ABG7AB24ewDbE8sOY7jwYHNmADtiRsyxDL
AysHbOQewAZswJaEbYjlQS8ezqQK2IAN2JKwDbE8iMKDJoEN2IAtD9sQy4P9xgge2IAN2PKw
DbE8qDMjeGADNmDLwzbE8iCa774BG7ABG7DlYBtieRDmnbdUARuwAVsWtiGWB+cRG2+CBzZg
A7YkbEMsD44jNnPuigIbsAFbErYhlgfReUsVsAEbsKVhW4dYHvgea3BXFNiAbWjY/gYAAP//
7N27kSM7DEDRlPTrXzjdJJB/CCvJWWPGgLX1UO8ogXGmTlECL/gvYWtRHuT3AzawgQ1sNdha
lAex5CusLQIb2MBWhK1FefAdHlgNDjawga0IW4vyIK9Y4wU2sIENbDXYupQHWyxgAxvYwFaD
rUd5cMZibRHYwAa2KmwtyoMYueUDbGADG9hqsPUoDz4fF3TBBjawFWFrUR7EzD19FQUb2MBW
g21rUR5k5Jor2MAGNrDVYOtRHsy8hfIAbGADWxG2FuXB+8S2pUWTYAMb2Iqw9SgPrtjDV1Gw
gQ1sRdhalAfXEY9hKgo2sIGtCFuL8uA64zn8xgY2sIGtCFuL8iBW2z3ABjaw1WFrUR58W1G/
sYENbGArwtaiPIhwQRdsYANbHbYe5cGeq3tsYAMb2Iqw7T3KgxFXHGADG9jAVoOtR3lwxits
9wAb2MBWhK1HeXDFYoMu2MAGtipsPcqDM55xBxvYwAa2GmwtyoN85akVBRvYwFaFrUV5kMsb
th1sYAMb2GqwtSgPvvvYPOYCNrCBrQhbj/JgRMZPvMAGNrCB7VfYWpQH14zXNDwAG9jAVoSt
RXkwZ97D8ABsYANbDbajR3nw2aArggcb2MBWhK1HeTDzlS7ogg1sYCvC1qM8GO8zm31sYAMb
2IqwtSgProxlakXBBjawFWHrUR6c8Ygb2MAGNrDVYOtRHpxxn/axgQ1sYCvC1qM8OOI2XdAF
G9jAVoStR3mQOQ0PwAY2sFVha1Ee5IgZF9jABjaw1WBrUR5877F5zAVsYANbCbb97z/Cfxm2
8Yh12u4BNrCBrQhbi/IgDq9UgQ1sYKvD1qI8GEtsUysKNrCBrQhbi/Igh6ko2MAGtjpsPcqD
fa7T8ABsYANbEbYe5cExr+nNA7CBDWxF2HqUB9u0QRdsYANbGbYe5cE+D8MDsIENbFXYepQH
kbvn98AGNrBVYetRHrz/XB5gAxvYwFaC7d6iPPjCdoINbGADWw22FuVBnvEK1z3ABjawFWFr
UR7kPrfpMRewgQ1sRdh6lAfbvI+feIENbGAD26+w9SgPtvmc3jwAG9jAVoStR3mQnt8DG9jA
VoetR3lwzJgDbGADG9hqsPUoD7b5GPaxgQ1sYCvC1qM8WMccLuiCDWxgK8LWpTw4lAdgAxvY
irA9epQHy7jGBjawgQ1sNdh6lAfryGF4ADawga0IW4/yIPMtG9jABjaw1WDrUR7MfKRFk2AD
G9iKsPUoD644w/AAbGADWxG2HuXB7s0DsIENbHXYepQHI95nNrCBDWxgq8HWozz4rAZ33QNs
YANbEbYe5cEy1vEAG9jABrYabD3Kg3UMSRXYwAa2ImzPHuVB5pUX2MAGNrDVYOtRHsy8h+0e
YAMb2IqwtSgP5pW38GAy2MAGtiJsPcqDERE26IINbGArwtanPHBBF2xgA1sRth7lwS339Pwe
2MAGtiJsLcqDeOYzTEXBBjawFWHrUR7c88gFbGADG9hqsLUoD+KWD9s9wAY2sFVha1Ie5JWG
B2ADG9hqsL1alAeRhgdgAxvY6rD1KA8eeaQLumADG9iKsLUoD/JmeAA2sIGtDluL8iC2XOIn
XmADG9jA9itsPcqDz/DAVBRsYANbEbYW5UE8XNAFG9jAVoetRXmQRw772MAGNrBVYetRHpw5
PZgMNrCBrQpbi/LgDZsTG9jABrYybC3Kg/eBLYZXqsAGNrDVYFtalAfXEvfhxAY2sIGtCFuP
8uCKPZzYwAY2sBVh61EeDMMDsIENbHXYWpQHuc7bABvYwAa2Imw9yoNtvqaX4MEGNrAVYWtR
Hrxhuw+vVIENbGArwtajPIg8LJoEG9jAVoWtR3nw+Y3NiQ1sYANbEbYe5cEyjmHRJNjABrYi
bC3Kg1zHGL6Kgg1sYKvBtrYoD96wpfIAbGADWxW2HuXB56uo1eBgAxvYirD1KA8iF28egA1s
YKvC1qM82Obigi7YwAa2Kmw9yoN9rtO7omADG9iKsPUoDy4RPNjABrY6bD3Kg2Vsw4ntfwLb
HwAAAP//7N1BjuM4DEDRKyWxndjHsUTx/kfo6toMMFULArMZAg+5QvBgW/wU2MD232FrUh7M
ZdwDbGADWxW2HuXBPvf5ABvYwAa2Gmw9yoNj3pIqsIENbEXYPj3Kg8gtjXuADWxgK8LWozzY
5zGfYAMb2MBWg61HebDP1/iJF9jABjaw/Qpbj/Ig8kjjHmADG9iKsLUoD1bkxzc2sIENbFXY
WpQH54jH7VUUbGADWxG2FuXBOb9gS7CBDWxgq8HWojyI14plQBdsYANbEbYW5cGc6w4RPNjA
BrYibC3Kg3Ob83bnAdjABrYabGeL8uC8Z96u3wMb2MBWhK1FefB9eOBUFGxgA1sRthblwbnP
uG+wgQ1sYKvB1qI8WHe+06ko2MAGtiJsLcqD6xGvIYIHG9jAVoStRXlwnXGMD9jABjaw1WBr
UR7cM8KFyWADG9iqsPUoD95rLRE82MAGtiJsLcqD+HzBtoENbGADWw22FuVBXCuXfWxgAxvY
arBdPcqDa+atFQUb2MBWhK1HefCe63avKNjABrYibC3Kg7mvT7h+D2xgA1sRthblQax8Lts9
wAY2sBVha1EezOPric2ALtjABrYibC3Kg/XOY/3EC2xgAxvYfoWtRXlwHbEP5QHYwAa2Imwt
yoN7i3u4zAVsYANbEbYW5cH1iWM4FQUb2MBWhK1FeXBfMaekCmxgA1sJtuufP8L/GbZcf39g
AxvYwFaDrUV5cO2xDa0o2MAGtiJsLcqDjHxaDQ42sIGtCluP8mBbsawGBxvYwFaErUV5kJl3
uqUKbGADWxG2FuXBlXEOa4vABjawFWFrUR7cEWuaYwMb2MBWhK1FeTC29ZheRcEGNrAVYetR
HjzjNVzmAjawga0IW4vy4BrxHhfYwAY2sJVge7YoD64Vn2E1ONjABrYibC3Kg8ycCTawgQ1s
Rdh6lAeZkcY9wAY2sBVha1EerGe+llNRsIENbEXYWpQHMfO5zLGBDWxgK8LWojyI/HpicyoK
NrCBrQhbi/Ig3mstiybBBjawFWFrUR7Ea81lbRHYwAa2ImwtyoNzm3F7FQUb2MBWhK1FebCe
uTkVBRvYwFaE7dWiPDjfc91gAxvYwFaErUV5cK54Dt/YwAY2sBVha1EeXFcc4wQb2MAGthps
LcqD7wHdD9jABjaw1WDrUR78HdD1xAY2sIGtCFuP8uBauQ6wgQ1sYKvB1qM8mPnQioINbGCr
wtaiPPge0PUqCjawga0IW4/y4J55/8QLbGADG9h+ha1FeXBmPIeb4MEGNrDVYNt6lAeH8gBs
YANbHbYW5UHc+XAqCjawga0KW4vyIK+c6YkNbGADWxG2FuVBHjnSqSjYwAa2ImwtyoO81yOc
ioINbGArwtaiPBj32ibYwAY2sBVha1EejPEFW4INbGADWw22FuVBXpERYAMb2MBWg61FeTDm
2sOiSbCBDWxF2FqUB7nlnSJ4sIENbDXY9hblQY71NqALNrCBrQpbi/Igr4gYYAMb2MBWg61J
eRAj3CsKNrCBrQhbi/JgPtYRG9jABjaw1WBrUR7Mbb3DNzawgQ1sRdhalAf5nmNqRcEGNrAV
YWtRHnzBtqbtHmADG9iKsPUoD/b5ni+wgQ1sYKvB1qI8yMxhHxvYwAa2Kmw9yoMz7nATPNjA
BrYabEeP8mCbjzHBBjawga0GW5fyYCkPwAY2sFVha1EejHO9prVFYAMb2IqwtSgPMnIl2MAG
NrAVYWtRHnwvmvSNDWxgA1sRth7lwTHv6VQUbGADWxG2LuVBKA/ABjawVWHrUR584uWWKrCB
DWxV2HqUB8f8TGuLwAY2sBVh61Ee7HMbrt8DG9jAVoPt3aM8iNzSExvYwAa2Imw9yoN9voY5
NrCBDWxF2FqUB7mNNdx5ADawga0IW4/yYJ+7b2xgAxvYqrD1KA+2kcMcG9jABrYibD3Kg23M
oTwAG9jAVoStR3mwz6fDA7CBDWxV2HqUBzMfyzc2sIENbEXYepQHW97pVRRsYANbEbYW5cH1
jNcwoAs2sIGtBtunRXkQn5ULbGADG9iKsLUoD85z5m3RJNjABrYibC3Kg/Mz179h+wMAAP//
7N3dDds4EADhlixZfyyH5HL7L+EUvSRAHJwe7uARMq7B+EBSs6SwCZuwCdufYHvE5MGRMbdJ
2IRN2ITtHmyPmDyIkfM4hE3YhE3Y7sH2iMmD43ArKmzCJmz3YXvE5EF5nVvRWdiETdiE7R5s
j5g8KFssbRU2YRM2YbsH2yMmD9oyXr0Jm7AJm7Ddg+0RkwfjncvwjE3YhE3Y7sF2PGLyIEeu
uQibsAmbsN2D7RGTB6PnnnZswiZswnYTtkdMHpQeuzfoCpuwCdtd2B4xeVDihM2PB8ImbMJ2
E7ZHTB60V2R38kDYhE3YbsL2iMmD7COHV4MLm7AJ203YHjF5ULeo3Y8HwiZswnYTtkdMHrR9
zN0Vm7AJm7DdhO0Rkwd1j+aKTdiETdjuwvaIyYM6RWm/4yVswiZswvYJtvKIyYNrCH4TNmET
NmG7B9sjJg+yj+GsqLAJm7Ddhe2LkwcfLpSsPWv8PxB9Juc/t0Q2ZOMvYOOLXf8HNiKmmrIh
G7LBZuOL1fwHNube6yEbsiEbbDa+2KT/4QG2JhuyIRtsNr5YfH983mz6+byZbMiGbDDZ+GJP
/eFj9RLvtsiGbMgGm40v1sof2Fh/fehBNmRDNphsfLEF/rBJWXvUKhuyIRtgNuZf/ggINo6e
Px8ClQ3ZkA0mG1/sWH9nY++9Vs82ZEM24GywKtHpdGOXDdmQDTYbqEr0etTbD7CyIRtwNliV
aI+XcblsyAadDVQluh/9qK42ZEM24GygKtE9e6ubbMiGbLDZQFWiR7hJkQ3Z4LOBqkSP9EhU
NmSDzwarEm3namPIhmzIBpqNiVWJjpjaSzZkQzbYbKAq0bpG7bIhG7IBZwNVidaM0a1EZUM2
4GywKtGIvXm7l2zIBpwNVCV6vQI4y4ZsyAabDVQlWnpszfs2ZEM24GygKtH6/vVpTtmQDdlg
soGqRM/Vxu5qQzZkg84GqhItzU2KbMgGnw1UJVpnNymyIRt4NmZUJVqmmNtbNmRDNthsoCrR
ssfazL1kQzbgbKAq0YsN79uQDdmAs8GqRH8ciRbZkA3ZYLOBqkRLlQ3ZkA0+G6xKNONoPq8k
G7IBZwNViZYtFs82ZEM26GywKtFdNmRDNvhsoCrRjFzSxxxlQzbgbKAq0YsNcy/ZkA02G29U
JZojt3STIhuyAWcDVYlebKyyIRuywWYDVYnm9ZMN2ZANNhuoSvRSwwlY2ZANOBuoSvREIzJk
QzZkg80GqhI92ejpzeWyIRtwNlCV6LnWWO02ZEM26GygKtEfJxuebciGbNDZYFWiI3e7DdmQ
DTobqEp0H71Vuw3ZkA02GwuqEj3evddDNmRDNthsoCrR8o63VxDLhmzQ2UBVomWJpblJkQ3Z
gLOBqkSPrY9qtyEbsgFnA1WJ7r3X6iZFNmQDzgaqEt3jZMPcSzZkA84GqhItr5jbLBuyIRts
NlCV6PWYo2zIhmzA2UBVosfSo/pOimzIBpwNVCVaZrsN2ZANPBsrqhKtU5TmKJtsyAacDVQl
Wmv07pcU2ZANOBuoSvRabXi7l2zIBpwNVCVal6jNK4hlQzbgbKAq0TJib8blsiEbcDZQlWh9
xeEmRTZkg84GqxI9Ym27bMiGbLDZYFWiNbbmNT2yIRtwNlCV6HWXqKsN2ZANOBuoSjQzm++k
yIZswNnYUJVo1gzZkA3ZoLOBqkTPtUZklw3ZkA02G6hKNLcTDidgZUM24GygKtE8smeVDdmQ
DTYbqEo0Rk7DD7CyIRtwNlCVaBZfnJcN2eCzgapEo+Vr+AasbMgGnA1UJZr7udrwSFQ2ZAPO
BqoSHXHC4RXEsiEbcDZQlWjP0cIJWNmQDTYbO6oS7a+xhlcQy4ZswNlAVaIROQ1H2WRDNuBs
oCrRludqw7MN2ZANOBuoSnS8ch5WorIhG3A2UJVotrGNVTZkQzbYbLAq0TZ22ZAN2aCzgapE
s48x/AArG7IBZ4NVifZ8Dd9JkQ3ZgLOBqkTP1UaOIRuyIRtsNlCVaI48vIJYNmQDzsaBqkRP
Nkp634ZsyAacDVQlmuHZhmzIBp8NVCV6rTYcnJcN2YCzgapEr3dSrERlQzbgbLAq0bltbZIN
2ZANNhusSnRutVmJyoZswNlgVaJbH90riGVDNuBssCrRrWf3VTbZkA04G6xKtI51eLuXbMgG
nA1WJfpjcH6RDdmQDTQbhVWJLn3r3u4lG//Kxj8AAAD//+zdybHrIBQA0ZQ02BIKB+6Qfwhf
fkn8XnR57+UpuGpANv4vG6xKdF/HdLYhG7IBZ4NViV6RYe4lG7IBZ4NViX7jCbsN2ZANOBus
SjQqvIJYNmSDzgarEp31KUeisiEbcDZYleiTlY5EZUM24GzQKtEIr+mRDdmAs8GqRFc9PuYo
G7JBZ4NVid65R8mGbMgGmY19Y1WiUcsvKbIhG3Q2WJVod7QjUdmQDTgbrEr07OmDB7IhG3Q2
WJXo0U9fsiEbssFmg1WJbi8bxuWyIRtwNlCVaM7efHFeNmSDzgarEv0425AN2eCzgapE86n2
di/ZkA06G6xK9HhXG45EZUM24GygKtHKHu0JWNmQDTYbO6oSjaOudCQqG7IBZwNViVa/qw1n
G7IhG3A2UJVo7O9qQzZkQzbgbKAq0Rx+SZEN2eCzwapEq79uUmRDNuhsoCrRPzYcicqGbMDZ
YFWi1aO9FFA2ZAPOBqoS7dnRSzZkQzbYbLAq0U8cK2VDNmSDzQaqEn3ZOFfJhmzIBpqNA1WJ
9p2f3GVDNmSDzQaqEn3Z+KZnUmRDNuBsoCrRv3dS/JIiG7IBZwNVib5sTNmQDdmgs8GqREfe
nkmRDdmgs8GqRLOPdiQqG7IBZ4NVif5eZXtkQzZkg80GqxL9zTZkQzZkA84GqxIdObzdSzZk
g84GqxKNercpsiEbsoFm42RVorO2NC6XDdmAs8GqRLP33mRDNmSDzQarEv19gDUulw3ZgLPB
qkSzT9mQDdmgs8GqRLtnT9mQDdlgs8GqRK/cwmt6ZEM24GywKtEfGyEbsiEbbDZYleidu6sN
2ZANOhusSjQqy9WGbMgGnA1aJVqyIRuyAWfjw6pEb0eisiEbfDZQlWg9Yw67DdmQDTgbqEq0
5sjhCVjZkA04G6hK9GWjxiUbsiEbbDZQlWit5xgenJcN2YCzwapER15eQSwbskFng1WJ/tg4
ZUM2ZIPNBqoSrWeM4X0bsiEbcDZQlejLxhquNmRDNuBsoCrRmqPHLRuyIRtoNr60SvTrbEM2
ZIPOBqoSfdlwJCobsoFng1WJPuMZPuYoG7IBZ4NViT4jht2GbMgGnA1UJfpuUj7pUTbZkA04
G6xKtH4/2ZAN2WCzgapE6+nL55VkQzbobLAq0ei7HYnKhmzA2WBVond/y02KbMgGnA1UJdrp
bEM2ZAPPxoWqRGs625AN2eCzgapEaznbkA3Z4LPBqkRHf6tlQzZkg80GqxIdfcmGbMgGnQ1U
JfrrNmRDNmSDzgarEv095ugVxLIhG3A2UJVonyuW1/TIhmzA2UBVoi8btR7ZkA3ZYLOBqkT7
WMvVhmzIBp0NViX626QM2ZAN2UCzcaMq0b/Vho85yoZswNlAVaLjjJzONmRDNuBsoCrRcUfN
kA3ZkA02G6hK9H5iTC8FlA3ZgLOBqkTvijm/siEbssFmA1WJ3uNdbXhwXjZkA84GqhK9I57p
80qyIRtwNlCV6JjRs2RDNmSDzQaqEr1vNymyIRt8NlCV6D3fTYpfUmRDNthsDFQluq7aw25D
NmQDzgaqEp0jV7jakA3ZgLOBqkTXXUekbMiGbLDZQFWic2aEH2BlQzbgbKAq0RmZYSUqG7IB
ZwNVia49O7xvQzZkA84GqhJdZ20xZUM2ZIPNBqoSnWfO5YMHsiEbcDZQleh8HInKhmzw2UBV
ovPKGb4BKxuywWbjQVWic8uxrERlQzbgbLAq0c+72vAom2zIBpwNViXa9U1nG7IhG3A2UJXo
GnVEyYZsyAabDVYleubjB1jZkA06G6hK9DnzXB/ZkA3ZYLOBqkQ7utoTsLIhG3A2UJVoHHWl
qw3ZkA04G6hK9F1srHQkKhuyAWcDVYmuo7bwDVjZkA00G8eGqkT726s9OC8bsgFnA1WJ/t23
4WpDNmQDzgaqEp2ZFZdsyIZssNlgVaKbt3vJhmzw2UBVorX3Ud7uJRuyAWcDVYnW0Wct2ZAN
2WCzgapEV9QnPTgvG7IBZwNVic6VGVaisiEbcDZQlWivGnXLhmzIBpsNVCXa79+2I1HZkA02
GzurEk1PwMqGbPDZQFWi14zzcZMiG7IBZ+O/V6L/AAAA///s3dER4zYMANGWZMkSyXJIAOy/
hOj8c0kHO5NtwJ9vaGhJ/IeNjO8wLpcN2YCzgapEn2vtv48iy4ZsyAaTDVQl+rT41zOFsiEb
ssFkA1WJPj3O4VU22ZANOBuoSvSZLxuORGVDNuBsoCrR51g1DtmQDdlgs4GqRJ9z7eHqaNmQ
DTgbqEq0jRjTLymyIRtsNk5UJdqeaNM/KbIhG3A2WJXo8EuKbMgGnw1UJXr/uQLrDljZkA04
G6xK9ONIVDZkg88GqhJtzdmGbMgGnw1UJdpG9OlpQzZkA84GqhL98yVlONuQDdmAs4GqRNsR
9/DlctmQDTgbqEq0XfEMX/eSDdmAs4GqRPsRa9ptyIZssNm4UJXojw1vwMqGbMDZYFWiFd/h
y+WyIRtwNlCVaPvEPUI2ZEM22GygKtHfnhSfIJYN2YCzgapEd9tLNmRDNuhsoCrRfey+3QEr
G7IBZwNViT4R1+iyIRuywWYDVYk+dxzjkg3ZkA02G6xK9PZOimzIBp8NVCV6l8/0yIZs4Nn4
oirR32mjZEM2ZIPNBqoS/V1lkw3ZkA04G6hK9PclxW5DNmQDzgaqEq1nf8uL87IhG3A2UJVo
fV82vJMiG7IBZwNVib6njbucbciGbMDZQFWiPzb8kyIbsgFnA1WJVuy23QErG7IBZwNVieZT
VbIhG7IBZwNViWZ72fBOimzIBpuNG1WJ5v2y4Xol2ZANOBuoSjTPinKZo2zIBpwNVCWa30pP
G7IhG3Q2UJXo70+KI1HZkA04G6hKdM26wovzsiEbcDZQlWhe758UZxuyIRtwNlCV6Bp1hnG5
bMgGnA1WJXrtq9w4LxuyAWcDVYnGVU/esiEbssFmA1WJ7qjtVTbZkA04Gw+rEj0dicqGbPDZ
QFWi+44WbmWTDdmAs4GqRF82ZjTZkA3ZYLOBqkT3yJUuc5QN2YCzgapEXzYip2zIhmyw2UBV
ovsb1zIulw3ZgLOBqkR3z56PbMiGbLDZQFWiLxvN3Es2ZIPOBqoS3SMzjctlQzbgbMAq0Z3b
SlQ2ZIPNRkNVojFr+CVFNmSDzgaqEo0lG7IhG3w2UJVo9OrpxnnZkA04G6hKNMZ72pAN2ZAN
OBuoSjSe97ThnRTZkA04G6hKNNrLhndSZEM24GygKtFYNe02ZEM26GygKtF15g5nG7IhG3A2
UJXoavWJkA3ZkA02G6hKtHL37cZ52ZANNhsdVYlWyYZsyAafDVYlepU3YGVDNvBsoCrR3fJ0
B6xsyAadDVQl+rJxpQsPZEM24GygKtE965OeNmRDNuBsoCrRl43T9UqyIRt0NlCV6I59VMmG
bMgGmw1UJbrvWK5Xkg3ZoLOBqkT3E2FcLhuyQWcDVYn+niD2dS/ZkA02G4NVibZWzdxLNmQD
zgaqEq3ez+ZpQzZkA84GqhJ9f3VM76TIhmzA2WBVoseM6TJH2ZANOBuoSrRay7+vm8qGbMgG
kw1UJVqtH81uQzZkA84GqhJ9f7XNj2zIhmyw2UBVovW0aI5EZUM24GygKtFqbTdHorIhG3A2
UJVonhVenJcN2WCzcR2oSjTXPspKVDZkA84GqhLNIRuyIRt8NlCV6N47t3tSZEM24GywKtFr
7eUyR9mQDTgbqEp0j9yZsiEbssFmA1WJvqeNXG6clw3ZgLOBqkR/pw1nG7IhG3A2UJXo3dfq
zjZkQzbgbKAq0Xuu6J42ZEM24GygKtF2xj1kQzZkg83GB1WJtm88o2RDNmSDzQaqEr3bWt23
RGVDNuBsoCrRezgSlQ3Z4LOBqkTvvWocsiEbssFmA1WJ9shjOtuQDdmAs4GqRPs3cjrbkA3Z
gLOBqkQz9qd8glg2ZAPOBqoSrc++ytOGbMgGnA1UJfqeNo7yLVHZkA04G6hK9I6V3YvzsiEb
bDZOViW6wh2wsiEbeDZQlehadaXdhmzIBpwNVCUavXr6TI9syAacDVQlOs48l39SZEM24Gyg
KtGR2ZYfYGVDNuBsoCrRmZnhB1jZkA04G6hKdD65wo3zsiEbcDZQlWifXmWTDdngs8GqRFvt
ciQqG7IBZwNViUbWcuGBbMgGnI0LVYmuqm8625AN2YCzwapEUzZkQzb4bKAq0RXG5bIhG3w2
UJXofvbaxuX/Lzb+AQAA///snUtz5UQShf8K0TGLmYVFvR8EsHQM9nKWxCyupBI4wo8OP3j8
+8m6UjcNWO68crU6YQ5EuGlu6rpSKn11KuuUBGz8BbEhyiU6uBJH2L2ADWBDODZEuUQnOx0m
YAPYADaEY0OUS3RyhA1MUoANYEM4NkS5RI8LsAbYADaADdnYEOUSHYZygN0L2AA2pGNDlEt0
8pikABvAhnhsOFEu0eInV/AIYmAD2BCODVku0VI8ahvABrAhHRuiXKKDJmxgByywAWwIx4Yo
l+gQShzxMkdgA9gQjg1RLtFi8DJHYAPYkI8NUS7RcZpMycAGsAFsyMaGKJfoERtYgAU2gA3h
2BDlEi0KagPYADbkY0OUS3SK0zChtgFsABvCsSHKJTp4bJwHNoAN8djwolyivStqgNoANoAN
4dgQ5RKdpqlMMJcDG8CGcGyIcolOesqTBzaADWBDNjZEuUSLnVzBxnlgA9gQjg1RLtFpmMYJ
2AA2gA3h2BDlEqUpChZggQ1gQzw2RLlEpwPUBrABbMjHhiiX6JBKHuESBTaADeHYEOUSPdq9
sHEe2AA2hGNDlks0k9pAbQPYADZkYyOIcoke9Jh62L2ADWBDODZEuUT7XOxQgA1gA9iQjQ1R
LtG+J2xMwAawAWzIxoYol+ihjGXADlhgA9gQjg1RLtHeYAcssAFsyMeGKJdof0BtA9gANuRj
Q5RL9JDGYcB7UoANYEM4NkS5RHMZUw9zObABbAjHhiiXaJ+KGeDbADaADeHYEOUSPaqNHtgA
NoAN0diIslyi/TgOeLoXsAFsCMeGKJdoysN0wCQF2AA2hGNDlEu0eDwUENgANuRjQ5RLtPdF
D8AGsAFsCMeGKJdoGkfdK2AD2AA2ZGNDlku0qg2spAAbwIZwbIhyiQ5DOYzABrABbAjHhiiX
aDlMYdLABrABbMjGhiiX6DCS2kBJFNgANoRjQ5RLtPRQG8AGsCEeG0mUS3QopR9h9wI2gA3h
2BDlEh11GUY8FBDYADaEY0OUS/SoNlDbADaADeHYEOUSHfpywHtSgA1gQzo2RLlEx1BKwdO9
gA1gQzg2RLlER0WTlAJsABvAhmxsiHKJjmUyJQEbwAawIRsbolyik5ry5IANYAPYkI0NUS7R
4+uV8MZ5YAPYEI4NUS7RcZh0wVvZgA1gQzY2siiX6JjKhJUUYAPYkI4NUS7R3hWF520AG8CG
dGyIcokSNvCYHmAD2BCPDVEu0ePLHA2wAWwAG7KxIcolehjxnhRgA9iQjw1RLtE+0iQFG+eB
DWBDODZEuUSnQ7EFj+kBNoAN4diQ5RLNRWFPCrABbEjHhiiX6BEbmKQAG8CGcGyIcolOfUlw
iQIbwIZsbDglyiU6HYqDSxTYADakY0OUS3TKY8HrlYANYEM6NkS5RKc0HkY8bwPYADaEY0OU
S5TUxjBmYAPYADZkY0OUS/SoNvC8DWAD2BCODVEuUVIbPdQGsAFsSMeGLJdoX/oCbAAbwIZw
bMhyiaYxj/BtABvAhnBsyHKJVmygtgFsABvCsSHLJTpOdoLdC9gANmRjQ4tyifZDcSN2wAIb
wIZwbIhyiQ6uxBGP6QE2gA3h2BDlEh1VGbBxHtgANqRjQ5RLNIfR9VAbwAawIRwbolyiOY++
x0oKsAFsCMeGKJcoYSP02MoGbAAbwrEhyiUap6E/YJICbAAbwrEhyiV6nKRAbQAbwIZwbIhy
iSY/lMMB2AA2gA3Z2BDlEk2JsDEAG8AGsCEaG0aUS3QaJz3BJQpsABvCsSHKJTr1JeLJ5cAG
sCEdG6JcoimgtgFsABvysSHKJRrdEDPM5cAGsCEcG6JconEcDvBtABvAhnRsiHKJHuLYDyiJ
AhvAhnBsiHKJjrlMBWoD2AA2Pj82vrybpquhfFU71A3dBcP83Q/ffr180N+Nv77/y8Pb+3IY
H34s5fHbr4/3/FfUw4en6/n+eSiPtdM9fPHuowc67+X2gbriT791oPnD337hdEVwuD705frh
DzFPdPx9+YG+/v6s/EK/++GBfs1zUT9fXdMc5n6kzx7vn8qbd627eiz3x7YtsTeHX65unm7O
xqtpKgS8ihvVUZfXx1OzntK7Lzz+XL5s7rX/qWdDv2vMh3x8POg370/dRBeg3mr3Nx+mfjc8
PXxAtfrh27fXv56N5aEScb5754+//F0TKk2fbm6f+a3D3fvG3D7d9OV+CX04m2Faxm/eBPcu
ZJwZP6P7Ofj/4dfe3/38zO+8v9Nv/tA8+r7nGlc+3rj0p1TXvit89Lss+7vqM6mWS/XT4fqp
LKh6eCT+/0AQpj5xpPoznz3bhoe3h9vbuQm/D6Az+MGnx/NWv/jtt/VepUF4/OLx7oubq1vq
qtQh54/e9czfcnh/+93ROFPGsz9lt3pKzF/0lPSP96XsfkZWD3LxA2K8vzca3yxm6wV4fwbr
qWWctE/ejioeiaUSmnL8TMRJqbJMREPq/319O9yr28G9xz/5Cenpr2f99d3djZjWsIeEjzQn
vr45pGuHL/6plP/X65uTGjTncfixNkeFBu3Jr24P6dnD9bE9sUF7cLn+Uperxfn5G1+u17fn
tZfrkwg6wxV09tn8p+u7w+PvPyEZvJRinjsp8wHvz8kc+vqro199dW7ubu8e725pakttOjs8
DK9v1AmnLLHOVtq1TXWHPucSBgmX7+q2PJ5dvf3Jvb4xnn+KQu6sSryLt8TuegmN7nLmXcY5
dOcO1llT34TO6mXH2F2vrvGdzZrXviV21/PnVedyZjVvDt21dTZ0OUTHat4S2wAkur4PZv6k
FiWfrg/fvLmbvvrm++47+98vv+/+8W/73xN6aOe9T9qZEHJid9XOt0CiC34lk4sNmdhOZUrD
eq9C1pGHrHpQg0xifbXXs5lcbsjEdCZ4bbX3LgZlmXTrTGyQSc7m5d51fkomqrMhWJdS0Fk5
6mCsVOioBqkYFdZSudiUSjQpqBRjyF4n55mpRNsgFWvXUrnclIq31kZjkw+a/kMzU/GbUvm8
ov7jSxqOX3Nvp+HO3h7GsYy7DvaxLqZFHk2W2H2lnOliYo5AS+zeYi5FyxZzNXZfMRc65z1z
tJhj9xVzuqMuxZNLS+y+ci6RwDW867vENpFzeW3AdbN0cKfJuRCzCl4ZGnI972TTQS2kgwth
bbzdkAkpM0OyyngdbXCJN0bRQQ2GW5JzaxL7ckMmVZnRgEtKzidnmRqIDmowkSY5Z1/uXeen
ZFKFWUw5aO20DTryZmZ0VINUXpJzm1KJJvtEXcsb5YzdVc6pqF7uXyem4l1ySjmfbUyBWQ2h
ozzkXBs512AcPUXHZZpVMUtyS+y+Os523JJSjdxdw9Ftz9ZwFLuvhoudqg+A5Jy8Y+i+Cs52
yTIrK0vs3gouWCb/ltgWCk6v0fw7P6sFf5qCy1nRuORCNly5rLvQYonJhbUy1sWGTOjmTsEF
5Z1yKTNHWDqoTUFuTVVfbsikirFAGZiqcWlex1VwLTLJ2b3cu85PyYS0mFM2p/ooFquO7wjm
KbgGUzGj/ZqsvtiUSojJGueS0i7xq1ihhRi1YU1XX25KxaVAWlRTFkanzC2Tuk0dDAruGQX3
WQpyuUueWVBaYvcWcikoZkFpjt1XzEUa9njDyhy6r5QjgaEzb/xeYvcVc77zgVuOm2N3bZ+r
VGQufi2xTcScXhtuwywcwkliLhgfSP84q7zPzL5KwvTTirkNmZAu88EkT19rgje8KQod1OKa
xFWBfbkhk6rLsvfaBJuc510S09kW+jrntQXvpXOdn5IIqTJf6z46UO/SLvNkaV2SbSCAjPtI
7zoxlUAzbR9Sjk6F6LhaLja4Ksb6j3SvE1Op/oPoqZNRIlnxAEtHaWi512q5x329cS52/vi0
GM4INcfu7Y2j+RGzFDfH7qvfPKkey6xwzLG7Xl+d+Odvid33+tI5iVyFOcfuPX9wilctnEOb
6LdV/1KctUI8Sb/V1UejVK4uOeaprgc10W+r1ZJNmQTnojLBRGOVYxqfuxaan/Tbmqa+3JSJ
y9kYr4wLPlmeVNA0KjcRcGtL3EvvOj8lk7owSoNC8vVfHRNPVNNRDeqKxto11XOxKRXvlLYh
KUd3C1/0tCgrqtVb/nJTJi4bG5RX1gWaIqAUt6N8+xxVOFJmWTNdGUvs3rY45ZgqaYnde0nV
aOaC7xK7r4rLnfbM67vE7nt9Aw0DzJL/Ertv+1xneIPsMbKJhls1LaVZL6TTNFyqg2vKmaRP
4NbgdAs16sLaMuTFpkxIvSUbvXNOW+bGk0bVxLg+yG7KxGXrtM7BaKUM04+xcZD9k4Zbq1wt
vev8lEyqGstJK68V5cMvwrkWlav1yc7FplS8V1Fb+hGU8Za7NrzNR/bHVNKasr7cloryVcWp
QD8SanA7irh9DVOkyKJ1PIAssXvX4Jxn7jNeYveuwXmmY2oO3bsCZ1JgNm+O3b8C59n7Z2vs
3hU4y/WQLbGftgaXZ62QT6zBGa+Tz3RzaObSUKsa3KpR+2JTJqGuniYTbdaBOb7SQQ3G15dq
cJsycTmlqGmU9fr4ng0RNbg5k/NTMqk1OKtSvSI6ZM/e1tlkS4O1axflYlMq3tI8R8c6OdAq
clP51EW4Tam4lKN2Sln6ZqW5UhRVuBYC7rNU4VKtvDDXUufYvatwNmTmYtYcu3cVzjruWuUc
u3cVznnHLFnMsXtX4UJktm+J3bsK5xJzXWWJbaLkVs3nWs2ygf48SctlZbKl1nmruN7NNlsC
XqjFbcwl0ODkVDQ2m+C5GqhRNW5VzW3MxeWYlPXKaJ+Z+zqb6bnV59ksuZyflEutrdkcQla5
akW2l6xNRW61uHixMRnvbaJ/rPU6KOZUrlFNjjTxR3rZyckoSkQlp70Pmjma/l3LcvzHn58w
TDA7SJNpfrPNF5/hiXbMXQ1L7N41G625j/GYY3df782BvYW2xu56fav6Ucz2LbG7nj+Xu6SZ
j+FZYndtn61r9EwlvMQ2UZqr1nitF0WjT1U0wdlYVYDjTjzaKJoXHoSyKRfbqWqNr1tpVeRO
kumgNnsvVjc6bsrFdMYYHZNP0Sj+TtoWT9rJefVJO0sq5yelUvdfGJ2iMyHX/ZtcbWabrJeq
1aXfjclEnVIwLpjstfHciltscGVINX+sk52ajDfGB5rIKF33n3ONldtWZ6QLzf+bB9yRWvOe
uRa8xO5dwyExxFR2c+zeyi4FvrKrsfsqO09qlynsjqG7nj2vOqOYc9oldl9dFzvF3Y62xDbR
daurddos+sGcpusSKbpIuiR5w5zGNXKOubi6XLcpF9ORRE3OqKRMzswpAR3UwpkYVyu7lxtz
IX2ldNIp+5iZ1VASdi2KbsdXMbzYx85PyqVukdWkgWzd7xwzc7NMo421Wq1PHrYlE6tItTn6
6h5lP+euha574bHFG3Px9JXeWRq5bQ6Wrevw4OJGuu4zPOmOuetuid1b0AXHmynNobvLOe4T
YEP3PwAAAP//7H1bjuQ4suyOBKe/SG4ggVO5//1c9xALuDh9mG3iMFmPicJM94+pKyykEI1O
d7O2ow3kmZhTsEXlhp4Vc3xVcCbjhp6WcqIOOhXf2C1Sbto4X0bKQXkYPVGKxXqX1q4KCvuy
eBqEm6MscZGrCEvhRkqNwWmovGiLlJuVTj+XuIQqK9bcMhGkEjgws6dGxxn2/PUz9vGIC2Wm
Ts++2zStaeCxSl61gQzbvz1kT8m4Z7tlTwtmc7hX0XekaZQ29cReJKOVTNxIeucK+q7nVW8t
t0nL/SLPu65gR//Anu4DUwVV08CeFXUvHxmwz+/GnpV1WTkCx0Vf0LOyTmKTAC4CA3tW2LV4
okDPu4HdIuzmHVgj76A8DKGITyZCXXpBj+LLlj70L89eV7jIRRp6LqSQxb/gULE9tinTkcgl
KlmiK9rZQnR32JlyS/Nl6LrpSNDg8vGISyg0ac1jxx9kQnLDum7HrAPrrHb6Y5GMh0LNnjh3
pSroDPEmXTcvBK+R0Rb3w7KfVEnAlvS86q3r/uPRjfP+d6AUuaFnlRzHXwkqkRf0rI6zNHMA
ddyNPXpvQzt2RZfuG3v27lo+UPDkbWKPd3GCleFNkQelzNubRuZBeRZEUbSFjDMic0ENfq6y
Y1r1q1mNNS4uUjo19coNTDDZNqsxzYZd5JKHX1bIunfQXrEsLq//6KCbGvMMKh+PqLzyxNxY
zSppZVjFffPw7SIZk0pOlXuNpwyscWwav/0ij2KRjLbam1rh2GMKXGp8D+DuUHG/aAA39Dqo
5m7s6bNW/Kj1/Ekr6iB4Q89KuXY5oSXDG3u65OqOxmLe2NNSrhWwCWhgd8g5njc1jdSD8iyK
omg3j/c5tYb6lO2Sc3MblUUuro1KqFJVFoVHb/cYqczPwda4aC2hF5ibUoHvy9ox2D+qcnM9
N6IPHnFJZRZMiolxRiCgtZ8thsZfjd6ukbFMCWFrobeNCZ0j3nFkwDy9M5+LZOLHH7fm1T7n
CieMrc1DvfXcr3XEa6jB+8Aer8s1MPVsYE9X5szBZuyBPV2ZS0MAtDKX2NOVOe3g7ndgj1fm
pMCeeIn95urcCEEoD5MptBdSM9LqfljOzWcP17i41PoaH9CqYLbYtmyKeXVujYs2a94oNHav
sMPNjg0rv3IXvnzGPh5xyfKcMnn8yaxY1K5DdkjT+ejAj0UuJlnLltiLxMMGn7GujQ78bzI8
79BcIxOSNGc6xFuJXw5aanyfse5Qc7+oOicOqvaBPV2d64ba493Y0xU6YXDRH9jTNboKt/Xd
2NM1ulZR+7kbe/r5I7RxbmC/WdSNVITyMKoiXuyx4lKvVhy2Ov7uGt0aF1cX7mKdqBAs6r67
RrfGRasUEY33Qiv40PF31+hGMsIjLq8anTYuxeNrwvNJ99Topkm+PxbJWPzhSpW6WgcjUTbV
6Eqbq7o1Mho7htg3xH85XgC4a8lfWaP7Fns8tIM3cBteQ9smNY4b5BXw4buhp8s3jvpGvaCn
dSZ3XGcm9ui9zYguRouvN/bo92eZBA6+xgf26OeTPL4HW+cHdovOnJuojPSG8jC+oXnLQkie
Bx1N31KfLZo/lqikAWbpJVZMZ+5gvS0v2iIz54d0K1xyhrZIMCELaSYnB2+/NMcbAQ6PuKTN
HUlRy7a+NJY7aY5H0264H4tk4odSGvd4XzNTgU1UdhQP2eZjQGtkjEU8fis5o4W2yL/N8f4C
czwBj+UG9vSxoQsozwf2tLJrBu6WB/a0smvgsNUNPa3rTBjWdYk9retaRQdvb+yWHr+p2wWP
GAd+GOOQbrQ1dj2lEhrrt6VO9dXg7RIXvnpvLZ7T3rUxqutoh39znZZ1PxeplJbigT2UXevY
1nrP4G3ouqmv9uDy8YhLKrTKmROrVFgrWqTa4o0nMtV1i2RCnFbK1sHYYgmceLtF14lPzfEW
yZgQV888Pm0EOzi/zfF26brj5nhewJGpgT19JNeawEfCiT0u6AQ9cr2xpwWdNHQs4saelXTZ
GweOUg7sWUlXL3IweXlgt0i6qdEFj7wEfphjoa1T+uQxkaPJXLpnCnfaUb/EJR4C817EJHQD
g1FFcdGeHIupzcUSl7QuLo2rZsxIAwfTdtkdzyXdSEt4RCXEGYX4sR6bBu0K6tO4akMN9Ssv
lUUy7lVfMw5FmoJG1Ju8VOhfH7KnZNTNWIXS9Q899np75P3hHnmNYh8LrvwDe1bZxWpZ0YSy
G3tW2dXM9gCrHzf2rLJ7+QY+sBg8resa+Ka5oWdVXbsKaq/7gm7RdNMWLB5ZCfwsw8LIVbma
pX5AZzc2GR/Py3QrXDJmrMXWg4W4N7BlMS7aUXKs0xHpzyUufIVMJNPWQmuzwAZ5e9r8pkf8
g8vHIy5pkEfGzZlacfTgJ6/aIurmdbo1MqF9REXjOeuCWlJvEnVM0wmhRTJaXayE2CaKnyNs
rfIe3vjPhzeOG+TFNgR2yEvsWSHHVxO0a/7GnhVydlkDPWkG9uj9zfFaNNBtYE+fqTc0WGFg
T/dyFvjz3dgt3XTTViceeQn8LMciVFWroYTJO/o+3za1MV9p17i4NZfYUcY/DM7k2NEr8tUo
7iIXbTn02bUbEejfsW0Ud5qVMrh8POKSU7XOr/hfCu0AV4K2OOXRfN57kYypFskGVOsFNR37
fqe8RTLaaujsUKXOHX3M3k55f7BTXqzkHXvL39DTx661gK0/A3v62LU0dAznxp7VdC32Z+Ck
9cCevb9+VQdDjgf2tKarFbTdfkG3FOimxhc8khL4WYBFSM1OUtOchgpsrrIlwKLOD8TWuLhJ
Jy1qQQpM3Ns1hzvtb/xc5BJCu5OxVRVBHTd3zeFOQ1IGl49HXFKbWeMqsWuIZw0fkNghT7lN
vY8XyZhlEVhZ4+44PCDx3XO4i2TiZy8lNg+mhdEWnL91Dvfv9sprV+xDQK+8G3u6QNcNFCMD
e7xAZ+A45MAeL9AVcOP/gh4vzxX07t7Y01KOOpqxcWO/uTw38hL4aY6FVurdiM3ApWmbmJuX
59a4uHXpltWGomC/+oHy3BoXbVqk1NqaE5jlvifIIsTcvz1jH4+45HxD711z21Ae+B7vccqb
a7k1LiZ5PsnN3BnNN99UnfsijWyRTGzQK7HEyiO1gHNE78PWP9opj8HyyA09veRrAfd6A3u6
OicFbO0b2OPVOfDTJfJ4W2RHR3Bv7Gk5l6OUqJxL7Jba3LxbfeQl8MMci9ibC2tXMnT+MC/6
Zjm3xsVDycWPSLkVuOi8Sc59UZtb46JeG+W0bnXY7m9PaW7qKvfzEft4RCVLc5wSW7gXedXK
zh22iszrv2tkzOMtXUpo3tq4wnLuu0tza2SyNGcubG7UYPPCv7M0x99hkQeag50OZUAlyYY3
4wbp+4ts+xj0aL+hpyuZVMCRv4E9Lnz5gfDlw8JX0k8XtGob2KPfn6UrAvg+Htijn0/qxWDT
xg3dIn3nPf0jW4KfZUt0aVqsSvde0VfitcWC8AvfviUuchWqWS/jUFraMVWyy7dvWv37XOLC
FzfNMW1Ps2u0oH/taGwJ7Tu3EBrREo+4hMJKfxeX5qaK5gvTlr32V759i2TyeL2Icd4eUlTI
7/F3mdZlPxfJmOSkVW2tFO/wrmStLvu7a9//Kt8+btjCOrCnhV3s9+Ej6sSeFnatG27z0td8
LteFnV6lVXDTdWPPCrtyiYObwoE9K+z6VQQs+A/sFmk37+8fCRP8xPs/djzp2mXdyaijQdfX
jt/SlyPBK1wkw8EL3R3xaPtFXrSlqjk3VVu7L1LiiXbLLj0Gjw/jog33JaTd3Epo5Es84pLF
s9C+hYVbBRtBV+cU/iHs5ruHNSo1889iF5QqtYEjjHHVlgmSaYX2c5FM/k7i56LSu6G+36sV
2rew+x2M+wgslQzs6XPComBT5MCeV3R4xkY7nbERKi191VFFl9izik4vaqDBywt6XM+Brl03
dIuam/f2jyAHfhbkQMKVJP4pL/MYTMxtOaL+wrNvhYq8fO7IY431YmA5SLYY3YWYm49qrt0W
yVP2ENi119YOi7m5h9BIcXjEJYSZxF5GLW4L1YrX6XaUtorNfi8/Fsl47cGHrRfpCs/Q+p4K
6nzLsHhnemneQ6AGHSqoneJ7IHibnPsVdbpQat3BVX9gT6u65nj3V2LPqrp6WQXthAf2rKqr
eWYOqrobe1bV+UUEJjAP7NHPpyVXX0y1D+wWZTdt9JcR5SAPoxyK18rcObQdw1EOe+p0U2m3
xCW2bs1juY0VsAYl2I55RyxFnU5sfy7eFzEyVRWv+G3ZEzY2Nf39+Yh9PKLyMv0V0k7V0/EO
NhTZYnbXpgG9i2QqkXItOetsDfRUzKt2kKnTGOhFMlbcM8ellJdfNlqoeyen/cfK7rxznzN4
KjewZ9VcrJCEuoDc2LNqzuI7AZeUgT16fznt60G1NLBn769dFayC3dDTewntaDPnjd2h5WTa
5i8jwkGeRWsIvQpbItUcdMjNi3ZouTpfZ9e4uDZ1jx967QJajm5zeZk2+S9ysTxA7i29Xryg
Q85rPf7/EHPTaaXB5eMRl5Bl7J5W31kNgktBe/rP/u0Re0rFlCqHmms5Fwy6Im2aC2aaloJX
70tPa8iuafXN4PT5u0j3R7v29QbW5wb2dB8dKToZfGNPn7oWsOf0hp7Vc/H+bw3Ww4k9e3f9
MkH15o09+/k0Fh3wQOwF3aLnpq3rMuIb5FmshogyeW1WQ9TBem7PZPDUIneRi2vmi3WhkA3g
ayEv2qLnpoHzi1ysUKEszmkT1IZ5R9pJyLnpBM6g8vGISggA7Z1MWial4em3OyJ8MqX2X56x
p2TMhJpQ6CAxdVjQ7SAjfXrqukqGenxF8c94ytDhKFp8zN6C7lea9tWrCjhlNbCna3OoNdcN
PV6ZQ2fUBvZ0ZU4FrS3d2OOVOTROaWCP1+Ya3r2Z2C1abtqrLiO7QZ5lN0g8eJZRB8XcUNO+
HZGkX9bm1rh4Rop1z/M8BQ8VDtTm1rhYVhiZ1GKNBSXDttrcdOZmcPl4xCVrc42astVGVPFG
re+dDv2xSCb2jCXUHJc0YgaPwDdV575ooVu9M/GIlV6kSuEKTp+9q3N/tGufgPWHG3q6Npc7
PrQ2l9jTtTlRtOBxY89qOk7rbPj7S+zp6lwz8C0zsKerc5VA38OB3aLppi3rMtIb5Fl6g5ia
UyMPKQTXtLbUGr+qz61xcRVSqkRdcSuWTfW5qRHzIhcrxUKcdm+1wtZ9mwp08xrwyG54xCVL
bZneS57RGui8yib7kjL1IfyxSMbijyt3il2awZ2AW6z7pM53DotkSvxheuWdONwJ+HcW6OQ7
rPvAqsmWl9C2YY3jJnnoOdcNPV27yeRNtHaT2NM6kyvobj+wZ3VmvwzNWx7Yo9+f9gttgb6h
Rz+dpK0heEY9sFtU5rx9fsRKyLNYiVaaFbbM+jDQjjsu+mYnlSUu8RN3NpZWxJnA4ai8aIvK
nDfPr3Dhi4U9npmmFEIT9cjbUWujMh3vHlQ+HlF5NfWVWvIQszVT9OB0U+FwaqWySKaWVP1M
8bshtHU0rtoxFf1yXP3yIXtKJn4tzMS19qzqwtFt7wmNXXLuV3nkgecqN/R09aZ3dPL2xp5W
dbFgwnYqO/b9z4yPGa19DezRb8/oYtC+9oae1XT14gdDy3sSP6Yr1P/ISJaQZ8kS8czF+7yo
eWugdMiLttQN58d0K1z46k07ey1kjcCBgLxoh6KbzjZ8LnLhwmoUz7SHCoIl3Z664XyuewRL
POKSjX3NmNN9xN3glIwtjX0i823DGpkcUK/ZbuANnqDZJeloLunWyJhYqx7PGWn8at62x8ft
VI6u97VnoRh7mQzsaTXnDrrPDexxNYf60AzscT3HDAdZJPasnuOrMXiWPrCnFZ0p6sN2Y79Z
043IBHkWZRGaTkr8PxMgBO0j26PpvvBRWeEiVxEuFKttL94wSSd7Aum+KtKtUAl1xtaFvfXa
O2jdvKtKx/Px7pGX8IgLXRJCuxWR2lwFbu/b0Y8d3+K/PWNPyXhwiAesU5fq8CTxjubj7Cj8
l6fsKRmtnNEvWrKAWr/X4eYt6X4jhzywSndDT/eAKdjHc0PPqrpcycHz/YE9q+rkIrhKd2PP
qjqJWwaq4oE9q+pavKo7aMF2Y7eouvl45EhLkCdO9iHQGvXWWyiIyqDxcV70zWevK1wykEJj
HbfuISHAquOuFIuppdznEpdQaCTp4PyKKSM0XWSHiXPIunmH30hLeMQlZEDhSqVnNTgeNrjD
b0fZkXV2Y34sknGvnaVWESa0JzbtkneUHb+YDVq8M00sDRjry+0PvTFLv/63qvu17niG9oEN
7FktxzkNDh5I3Nizas6uWFbgGdzEHr2/5XVIDja139iz9ze+E3D28Iae7uIsHSydvKBblNx8
NnJEJcgTE/tysWm3blo0tBw638DfPauxxsUlPTsKBRN0NHrXrMZ0ZvVzkYs2764hGBQeCSqb
Qrym2Wo/n7GPR1xSk8XT1cWVqT2Y1dih5L6av10jY1LFiqvHD6eBv5hN87cyzc39XL0zaXBD
WQoOmQ0nkr3nb3dIuV80fwtW+1/I0yeuijYMv6Cnz1uzzxw2xrMdv/iHfiro6PILerrqCvZA
BfC0imug3+EN3aLipo3qOlIR9IlhfQiy2I0XD40Zb/OCuqjwhm+6vB66/3uBXeTixhl77p1E
0M3JLheVWbfZ5yIXrY3JQvxkkxY6o7LDwz1U3HSqe3D5eMQlhyHM3LWQUEfHh3cFkc0t8RbJ
xOu511aqxc/FGto5t8USr7RpPW71znSXJtxaPmd459xS2fet4n6xJV4DRcjAni7IOaOmaTf2
eEHOQeODF/R0OQ62ZXhBjxfjioIK88aeL8eBIvMF/WYhNyIR9FkkArul0Ui33tFz7G1CblqO
W+SS5TiK1bVVxQd0v7sct8gldbV06VVVYG/jTeW46cHq4PLxiMvrYFXJuef5fQHf1rsOVqdT
Az8WyVi6GteiElsGxu2Ad6hSpqkd3uqdiQVbS7FMJShgD9W7HPdH2+EpOrc3sKdLcl1RPXdj
TxfluKEHrDf2dFGuMlrTvLGny3KtoUMuN/b080do2scLukXTTUcOdcQi6LNYBI776sStUwXP
iw/U5taouJG5UCy6jfG0iu+uza1x0dpJxamG3oZTRPbU5uYOx4PLxyMuWZurvZOQlDwt/m1q
c2tkzIxq1SJWM7fipBveV7W5xTvTq3QvasylVJjMX1mb+xY3vAIOGZYdA4Z/sB8eGtN6Q0+X
bhxd5l/Q4yITDdJ4Qc9KzLhdCn68gT367Vm+mQl79Ab26OcTv4qi1ik3dofI1OkQpI68Bn2W
11B7dr5ZK60R7p2yJePWp05lS1zkKhT6shW3XgthS2ZetENlTsNUP5e4pA1Kq967NlXqYPLe
taOPmomnjouDy8cjLqky2bhXa3HL0dT0vGpHrW1qH/ljkUzc6njIJOSyKIMl3bxqi2Se9vEt
kkl12TMFRl/T9m87vNNq7hfZ4TlqoTKwp08MvYDDjgN7Wti1AvbMDezR+yt4S5+cb+lLsWag
8BzY08Kuu4Gjyjd2i7Cbn9aN0AZ9FtrQCpOlZau2Dm7h8qItwm5+WLfCJefBXZzVao91Fx61
3cHli1HbJS58ld7IvFYN3Y2W0HeN2k5NegaXj0dcshBYayWn2oIRSCat9LYcok7DNBbJVHYh
Lto7czN02mSLsBOfnwivkXmNM2kvrCpE6IDG2vH2W9j9DqZ44BN7Q0+fxrWOjtve2ON6zkD3
/IE9XarTisdWJPasoku3MvD+DuxZRVezPQ53Od5ieZiji9PVdgQk6LPgiqotvfCqSrzTUfOU
+s2WeEtc4iFIM900X6PWwdOtvGiLopsf1a1wyVJdCLrCTZgUDOHaZXNM856DkY/wiAtdUvNs
253NyUGpnVftUHRz85RFMmmekmYj7hb7ILTHb495yhelujUy6k2JO3vxSvCB8NsTb5ui+xWl
ukYXoZFQA3tW2tWLHPSLekHPCruabb64K57s+PaeFOo4ljTw8w3saWHXCRylHNizwq69jMtQ
V7zEbhF28wnJkZOgD/MrRJrUtJGDTXXzom8u1a1wkYuqcivUcrIQ9TreMZFU6tSx43OJSvze
auslxEPPUzI0imPHWUnp0964n4/YxyMuoQOoaG89PUhqA9sq8qotum72e/mxSMazv49i98DG
BcwN36TrmOYTQot3plYyKtVKv+uAb1e8Q7ruvCteBecgb+hZJcdXvLPhEdzEntVydjmjRmM3
9ujdLT12aGCg4MCePlRvFdRKA3u6l7OgC9PAbtFy816nEZCgz3IrWC3+Z6HjQs6hx66bfPHm
6+waF890+VieiBmdRipbIgW+HMRd46ItA4lr7bFHBsc9tzmqTF20B5ePR1xSllXr6rVYKxUe
2thjizcvBK9xsQx5qLWV0ECi35ve9WAOd/HGNEv/gkLZvAn+Yt5zuH+wLV69Yh8CGx0n9vTJ
ay2ghcLAnj55LRVdWW7s2ZPXfG3CY7h6uk/Sr4p+ewN7WtLVDpYPB3aHpPvCW2WEI+iz0Ap2
jmW2Z5GugHWgvOibJd0al5B0meDVJN5F8FDxHkkn89V2jYvWbDwT5tLA7oOyeB72YA53JCM8
ovKaw6WQQBqiIcPpT87hyhcTEmtkzIlaCw0kNRQdSubb53AX70wPJRevzhB1OVr8Xz2H+7d7
5DUCCxADe7pA1x31Ubuxpwt01sHvb2BPF+gM1po39niBDmxSu6HHy3Por2Ngt2i5+UI74hH0
aWyFebdWuIV2QEXDt2u5NS4ePHrveUzZwBD3bVpu3t20xkVbqeTeC/cK9tBtK8/92zP28YhL
lue6meRMdWgruPd+U31uPhWxRiYDokNid+V4YYNzRLtiK/p89mbxzrySB3u2GmoBq/Pvs9Y/
2iePOxpEdmNPr/kq4ED8wJ6uzwlY/7qhp6tzogJ+ezf2eHNkJ7D+dWNPa7qOOsC8oN974Goj
KsEeRlho7M9Zmsu9+/8tDlwXubhTcfdWqSv9LtW5RS5aQ1k1ZpJK4GjorvLc3MBkcPl4xCXL
c4UtRJCIFJTMJgOTL8pzi2TMKTS21ZB0XGER9N3ludU70zPll6hp1wJnyv6d5Tn+423yHkkT
UJZseDlu0L+/yryv4T4viT1d0SQBYx0H9rj6JTy6LbFnK5qkV+xmwQ84wEe/QSuXNXD/NbBH
P59SelZiT+DAbtHAUx8OGykT9sT/3y8taVrBscOxAobS+RZ58tVk8BIXuYqLUYYZMIGzMHnN
Fgk8LTctUeErdibdS3OTLJ+BAySbJPC0CWJw+XjEJX6bhXrGcJBIB9/ZedEOLj6N4l3iQtlb
b1xT/sau0dAQtx0+WfFXTo0iF8lYI+ves6Sp+GTPmgXI766A/5ss/CqYcH9DTwu7WtDC1409
Lewa2p47sIeFXfylFR12GeCzwk5yOhIUdjf2rLDTKwMNMGF3Y79Z2I2sCXuSAhB7CvF0r6Au
maEKCrsdU+JfCrsVLi/Llyax5EqPnRLor7jJ8kXmZacVLpx5JqpdScwZtOLhLXkmoeymli+D
y8cjLiHSJH1kQjo4K6O2QluC0GhadP6xxCU0mjN7xu21ksG2qLLbUdt8HZR9+ZA9JeNKjTKg
W2ITAUZU0mIQ4lvZ/QYefooO4A7s8Q4wBathA3ta1HXUDGRgz4q6QldDD8Ju7FlJ51dBfY8H
9rSk84bOWt3YLZJuOrxpI9jBnljue6ZUWbzUW+WiFa3VbfGY1joN3FjiIpfEauul1GyQR7NQ
rh1dGCHpZvflc4lLqDOVoFGNuxS4WLcjdThk0DTUZXD5eMSlXNLVMnKD0xAMjduTHanDPJXa
P5a4hDijPOEtZtK8gV5jcdWebsp5RXiNTGwXpAoXltZR47TVs/e3pPt9TPyKgcpuYE8ru6ag
ffTAnlV29TL08w3sYWXHV+8NLNcN8Flt1y8xcLhkYM9+vleUAKg9b+w3l+tGtoM9cd33S5U4
w3qFCM2G8y1xCKHtpkZ+S1xCpjUOjcqmwg1Mhs2Ltmi7qfnLEhe+WlUPPeSuGjoC1HZty0Hs
1JXw5zP28YhLyemSUKlVyLKLD+2r3HMQOx0uWeKSR6oZUcNkmaYGnvZvOogtZTrCtEjGX+bM
LY0oCT2ci6vekRv/sbY7b+TnaLz8wJ7Vc7GXQ8ciXtCzas7imUfTNm7s0bsrLRQueNY2sGfv
rl/U0TrsjT37+fQqaEjXwG7RctMpThupDvYs1UGb5oRHc/UCzmLwlonU+FvnR68rXHJEJP0c
zbs4GtRStvjlljp14/lc5GJxW169TjVWWbS2tWUedX5c+fMZ+3jEJWv81tMAT0RZCT3h21HY
jm3KXMytkTFthUvsHWuxCk9i7DgTF5s31S1yIZfQ2VabddQniRbbHd9a7jcw8msXoScYA3u6
o45Q0TSwpw9ff2sjP+mxPUOTIm7s2ftbLzbQPXpgz36+NOzB3WkSu0XUzbvYR6SDPYt0yKat
WKNCBxGBh69x0Z5h4RmXH0tcQp81tVj6iuVyCw8L7ynQzXrQPhe55ORPcUtf4wImHZbFHvZ/
iLppmsvg8vGIS8ozFVYnU3OFh4W3iDqu82HhNTIZfxJSsXSn7uALNK7aEqHG00CXVTJxX7JX
gS32QuBg5DsU98/08quKzvXd2OMVOjQQ9wU9XaGz1uGojcSevbtySQWtqAb27N1tV2yEwQrd
jT1eQURPgwd2i5ibN66PSAd74rbPV20h5e7mIPS0NS/aIuZmXH4scSlXo6zPaanU0ez5vGiH
mNN58WSNi9cipYsW6h33Jdxz2jp3fhmJDo+40NWpxYZBlTz2NOBIW1y1p/tsvmNYI2Ot9R6r
iXqzVyobpn929AWWPvcXWiSjVkvOR1T2qrDL9NJe7i3mfg8vvwqeew3s6RJdKA24RJfY0yU6
PJHqxp69vznTgpUxbujRb09itQXfmDf07Kejq3Rspb2hO/Tc9NDlf2zkOdgTq325iKubU2gH
bnB07JYU3DY/C1uhUq6unbMAZELMaGRI3zLrqvOqyRqXpi1WWm4tbw6cTrxl1nU6TPDzEft4
yIVe2XwvJ5OmaPPcjlo7yzQz5McSF7pCkXoJpS3KbGAxm7a4RbJM7WU+V8nwaywqc3Azb/C/
unlOvsPHD1z5dyz6f7JfnoGmEQN7VmHKVRiN6L2xpxUmN9BA4AU9encLpcIAyxE39ui3Z5QO
0NivdGDPasx6xWoD9kXe2C1Vw7kEGEkT9iQDIDY2XKV71qiqgeEMuRvaITN9PqOxwiWe0eos
PeN5u4CVtrhoyxEwzRXACheODXvI/kxPpWKgDUlctOcIeD7jPXImHnHJYJKap/PpslzBzLCy
GAP7j6LhvDK9woWuGmqv9tiVccsDbXRGY8txNs2HvNfImFiaRbuKesej6d6WKrsE3S8yy7MC
DkQM7Fldp1fv4HnrwJ7WdQ0vHLbDdcM0Ni5oN8dP8GllV8GBkht6Vte1+CtBo90XdEvtcDoV
6SNtwp/kALw6SmOtFVatsOX5teM5+ErVLXEJgRbbj1KbeIPbCPKiHaquTM+Cl7iEQOtN1aVr
enegDZey4Vz7K1U3uHw84pIC7cVFGmsHzwLKYtTEP1xVpn19S1ziLSMkVEWqlNsXCFN1O1z/
2KZbh0UyZtXJha1wdzAY4u2q8gcb5QnaVzuwp+WcK/iqe0GPizllNDzlhT0s59rVDY1mHeCz
ck4uQTfCA3ta0HW0vW9gtxTq5svtSE/wh6EW3llaDbleGMxI9C3pCV95Hy9xyYCKGpKh9JKT
uNhqm67ZW86Dp41XS1xCnRVuvZLFRq+hPnmyxX9k7pM3qHw8olKu9GLr5CWUXQW55EU76nTT
rssfS1zo8hqyNIt02rvDzX172i7Lvz1jT8lop97SllriHQAGCNFiBfWt6H4Tn7wQaw1sMLmh
Z2Vdxiw12HcjsWeFXb0MPd58QQ/Lun51tD3yJ/isrNOLUUOJgT36+bRcBJrA39Atdbqp44WP
4AR/FmjBVaqL1upu4JxDXrRF1E2daZe4yJUTke7ETEwOi7otMxvThNvPJS4h0FQt+yCV8jwZ
VXXf7H48uHw84pICrVGrvUtrr0EdTNXtOEkuPg20WOIS+iyWOdU8texZ3EZV3RYy067Yz0Uy
8YTFXTF1jR0W6Jf6dlX5Mx3yrIB79oE9q+X4MkJHBm/sWS1nl6Nt4y/o0bsr7cpVDy0wJfbs
3bUL7iEe2NN9nOKg2/HAbtFyU6MLH4kJ/iwxQWvcWc3ynHaUzq4C3XQ0colLuXJJCjaxzBJ6
a8qW9IdSvyierHHRbiKx0sZ/mQQdPtlyTvmFQ97g8vGISzrksTSp7FIE3HznRVs66eYVujUu
ptScQgFp5wY2Sq82nz2o0K2R0V5qLUrxc8mZjXeF7qCW+yXjtzVjC8Dx2xt7+tQ1HknYdjax
p89d4Xitsite65lDHhvYhDiwp8uvrmBvx8Cefv7SJwJ9/hK7RdRNDS98RCX4s6gE5WatF8ps
dPTrvnaMOxedO9IucUl91kg5VqfUdrARyZYp3DKdwl3kEhK7dc+xAnXYIObbRd1ISnjEJfVZ
zUDjYGTCYMl9k0Ne6fOj/TUyZpYhFmIUO6FvjvT6R4VuOh+xSoZUm2iLX3/8bv5/Mv8PAAD/
/+x9y7IkOW7sFymMIAg+fuCYdZ3PkLS4i6tZXP2/CYhgaqEWozx4cXCqanK6rXoWHt3pycgI
Jwi435LZus3equ6bHfLQn97ERlfoKuyhdmGjK3RSwRrYxEbLuYamRExstJy77H0xOWfY6Bpd
R89bJtZFzi2nXetMS6jPUizMjV8f6EyqhdCv2ylttq8k0I8tLmYRZ15/qksldUb7730Mj8sy
LGqTi7BSUSWXwSFE2rSh/ZuWW8akTCIfj4ioKrN5iEY55zQqOL5uV3mQudkw7JGR0lSaip3q
1wYewDhlWOS03jHskSljkO7kskWrocZpby33WxvkFQKPvSY2ukIyGsMVEsNGV+j0oQxKugsb
u7509AFKkomNXd92VAHTxic2+li4NHBuY2JdJN16LmJmJdRnGRZiIwS9ceMxwFmC7OLIT6fL
8uKFu8NF1dmQSkMFXRZ0LoKO5mN7vG6h2+Oie7zUTwfDUuFhApc60J2qm0kJj7ioPtNfZyo8
dF9TKxguknwSc3Nb92nukTH3QkvyUxWUCFd1LmMeda3qNsnkmu0QuUjnBz10b6M8+IeMNql7
9Kf/xlZ5urcALQUvbHT5pjbQrn1io7VmRmdIJzZ0fc0Ajxh0e3uBQ79Bc0phsEA8saGfj+uB
hghXF1PWO6u8OoMc6hOL/WpDAdQtazX3BE60V5ehgNsJ3B0u5oaZWuLMqcEHW3aRi9Jcrcvn
FpesjwMhos65tw7ay+lFPkpzvZuZMQ6PuNi5dhKVmc1KuoyqZhervFRXRd0fW1zsIcM5S2KS
NgbYXu5kqsLLyZPPTTJi1j2qMzsRF3Bl/lSh+c9klVcz2OU3sdE1nCrgYMnERuu6nsE6xgkN
V3VC4IPpBQ5XdeDyXtBYTWdRgaBV3gl1qR+uazszz6E+sdqvB0muhUaiwQSOrdpFLqpubZW3
w8Vc71oVFXVMlzTBrPJ8VN2692qHiwq0osIhpVbyQKvoh0ey4a2om2kOj6iY/3FtmXvqlAhu
vHQSdesS9Q4XczIe1O2cXn826LPTS9Qt67qfm2SkWEaevhWTClRY073tj500XbhRnqAHwhMb
fSDc0ZGIiQ0XcwK2tExssJzrJoFwq7wW7qnCdsyLfcCJjRZ0+q7FPt/EuhTq1u/bmZ1Qn2Va
FJGcRHfqxKiDkvnrfXGhbocLH9SLvm+Fe80ZzIFgHyfnM0V08brd4WKFOjtnNmvqlGGvPI9N
ob7lVxPSr3vs4xEXOixpma2wRT2BP2knr7y8/L382OJirnel24RdKSSVUfdjF6+8nH52kz0l
U/SxnmodPSX93cCTuFu/mLeo+3W88prg2s6w0c1gqYAHYBMbq+3aIYwaPVzYYG039IcN9ne8
wLHarhyM1lwmNlbb6Y6mojWhC+tSrlsOS7aZoNCeJVvkkiVZ8aF21NW5utSF7hzztricjnkl
Df2fNcqhEb8+jnnrQ9gtLuch7OCkC677UrSr2esQdumYN7l8POJiMi232kfTDQQouZ2k3Y1h
3haV0zBvZKJWzdsZPIpxMszThfnJPfaUTBk1jZJEtXeu+T3CEWmyEvq6P0dsQfeSiY2Vc/no
8OzGhY2Vc3JUBj/fxIauL3drDwcLTRc2+lxdH//wubpho/s5c8EEwwV1kXLLEkqbyQntWXKC
bnLqYEqiWh0cYPUyzGvLXqctLmaTorIn5TKYG2gbRD59jo2WFZRNLqU3q52chUewpdTruHLt
rTK5fDziko6euu4WiKW0XBtaDfJxzCvLie9NMlKUQ8p28KpiGx528DgU52V34OcmGb3LdFn0
NstFN3To4evbMc9DzH2XY14Bjw8nNvr4tcEWHBc2+viVGtiLOLGxmm4chD6UJjZ2fS2LF5wP
PaHRim7kBt59F9ZF063i0f9qMzihPQtOKJZn2Un/QYXRgFOPyedbTbfDxeRZUtnAo0ruqC2J
j6TLq2X53KRSWh+jWuhsSWC6MW2eiT2QdDM24RGX0y5PSi8iY5izc6RdHq+DZzfJSE3c2cwT
mlTY0dllTPrGYmWTjFmskBiP0QQek37X5xwkXbhdXj1N5zEtZ9jo+pzegXCghWGj63MCjgtf
0GgllwWsvk5stJIjNDz9hEYrOWF0H3FhPZRcXR+CzdiE9izOQqiRmbIVKRksnOhFLkpubZW3
xcWs8oa+ljIPaSPYKi+vD1r3uIhqBRXXQ0qpYAAebYZG/U3KLSNTJpePR1xMlHFPZuKsW4aM
+6q4SLllEPCPTTJSRh2plpRH6Xh1zsctb12d2yNTBo+SB6ekAhXcMbyrc7+1W54+6kFFd2Gj
T+QKbEB7YaOrc5wynGdh2Nj1TUcrqFvehY1ukMwNDSm7sOHVYfT3MbEuqm6lhP5qMzehPcyz
GCNLa121HRzP4ZKbQKUtRyO2uJiqy01IuvUqgpVdculap9MMd/G+3eMiVq/npjqVBpiFRS5q
+84tb3L5eMRF9VmpufeqYrs2tK9Rr/IQQrx0pv6xSUZqLTmVqoIoNdAO1ckt7yZxdpcM8ag1
J9K1QQe9ftfE2TjN9n//8R//+M9//Mf/+dd/oZT+5d/+/f/9a+irCVvG6MNKUAk5PIwdNPc3
eQbqbxD2ljFsdA01oe0/ExuvuGFvGYWGrq7uQWiA3Q4TG/rtSToygY1qExv6+bgefYC+dCfU
Q23TusNxxlq0h7EWpQz9K+WUGbVSd+nXuvOW2eLCR+opUc61UqvgRs0u8lDbZbUun1tcbO6E
U+m6AWoldTQGxmdYJa3r9DPX4hGXdHAlGqpQuatQBTtI7CoPgZp+dpM9JdP0C9LNVdbNot5t
aNnRo/s652V25OcmGckjNRHdCOVSMnwc/rYM9NJz32QZONA5y4mNlnWtopWfCxst60YCJ6Un
NlbYVRND6OGzQmNlHR0FfDlf0FhR1w9uoJnbxLoUUdcdaDPaoj2MtpB0iYeece8Pj4O+W1m3
w0UVWkksRElKl4L6y3hsVqitrT+2uJhCG62ptEvcRoONoD1KdSmtxMPrHvt4xCXZzd8kJ2Ld
GTJIJvlMId84QW+SaVyqvulUnqbSwJePk2ngOhXvc5OMNZ/2rv/eweO0vfzCc/63rPtu18BO
1n+HrfLERrebmR8n2m5m2Hg9B74jT2i0mmsDLFZPbKye48Mm5FDHQMNGKzqpYNFhYl0U3boR
bUZItGexC2LzBFQHSaoDVnQeXG4cA7e4nD9x1u+5MY1KaKHOY5+iim5dqNvhouKsU+IuVTV8
q7Ci85lbWY9GzQSJR1xUm+XOkqimklsGz/j1Khfn5GW6349NMrUmVUBmnJ5VaqMiyGOvnqn/
7C57SuacDZfeLUsbzTtLm04Eb0X3i1gG9nykhhVlL2i0rOuoxdHExsq6plIXHCQ8obGyrh+Z
0WnaCxsr60R3kWDe3cSGfr6i752B+i9dWJfz1/XZ2MyQaM+CF2qSXMhyPXpG7ZCO6pFTcifr
drioQpOmL12qjeBYbr3Ix2FmXULZ4aIKbZiiU20n+gc6Jc4OXag5lZ/dYx+PuCRLBUxVRFWd
dAF3usklFjCvLZl+bJKpzQwDKRWmDO4dnNwCEy0T2za5lKFfUNUtu767Ca7TvUdY/v9VXbxb
YB3g431iY7Uc6QMPPDI8obFKTo6aGWxOurChq0uqzwT1vbmwsaur30kBv7+Jjd5JlAxuaifW
pUS3PhCb4RHtWeACVUvRyqwvJzTFRy/ycQtcj4rucakqSoV751EbeOhqF7loubXpxx4Xmyhi
MuMPlXSotYzHRJFKhrWWm9kRj7ioKutZ/6piEa/4sAd76B/m9dD7Hhkz6Tc9pxpIBLTOd3IL
vBNze2SK3mBEo7UmujBvt8BIMfdt88jgwdzERrfR6a4PfKte2OhjVxpoy/mFjVV146AEVpgm
NnZ9q76j0HnkCxv7+YolYYCf78K6qLqVm8lffcZG9GdRC6T7867Sro1eBI1Gdak23qi6TS6V
pQ+zpWs9gycLbqpu+b7d5FJGlVST3tajgj6OXqpuaZv8usc+HnGx8nRtnS1NsZeGJ4J5kKHl
wvzYJGOVxsqVdZtWwMAmJ5MZ6suI510uic3/kPUfXYXd2y8wTtTF+wWiXQITG12hKxms3U9s
eI0uobECFza8RsegF9kJDa/QJbB56ISG1+fgIcQL+7X1uT5TI/qz1AgVcUyjDKn6B5qA8dX1
uU0uZuJmCRhDOixKv7o8t0mljFEL5XL98YuU5yaXj0dczvKccG+qs4duaNAi0FeX5zbJCLdU
VPV0/UGjWU1fX57bJFMGpWyStCspsBv9XZ77re0CzbAcLc8ZNro8xx1sLDmh0cU5BscgL2h0
aa5k0Nx7YqNLc62g4XsXNro0Jwm1frmwLs1zy5mIPjMj+rPMCOr6qhUqkrIkuDTnMUdwJ+j2
uFSupWeLDZWOVp2/XtHtcbED19xHT1ISaiLvVZpbTlJPLh+PuFiRLRebpLbkvAE+sL1Kc2PZ
oblJRoRH42KhZtLAlXGqzfH42V32mIzF5lEqqTUL8/mjrQJ/9jEYVnQPXhNg+7fLQ8htUiPc
Iq+CT+sLGl24IXxCg6IHNFQ4orNMExu6tqdJMj8wVPbYxj8ZgRhHP/2tkB3OhQ39fFwPAm1y
LqiLxlxaBfcZZtEfhllY1ZBLqn2AVQMf1+M7I5UtKnwk4VJbJhkZbLayazwUZlmmxW1RyUem
lvj0LORM8NStixn10r/5dYd9POKSDhZR/VJU/esXRegZo5M93nI8Y5NMozP5LulmrzRQQDjZ
41Ff1wz3yIidFliZnXvK4Gs+bf76f3WF+U9jj9dsBUHVNLHRxZsxGly8MWy0rOsVzxkxbKys
k8POaNDDVsOGfn+SDrOgQn2PDRsr65r+N8Fpkol1EXbrvr6ZZ9Gf5VmU0WqmITblOdBsDp+c
kb50L9viko9h8XHZ/NhSQm/tY7jkjMhy8naTCymZajOe3DvoK6TSzmNdxvjZPfbxiItJO+VR
SSjpX3AvnJO0WxqqbJJpSqVWFXg9c82oTvVwpchZ1o19e2QkSz4HT0isgfTtfBws7eIt8iq4
yhMbrelqBl29JjZc0xWw1DSxsZquHsTgbnNiYzUdH5nBA9eJjdZ0TOD3N7EuHX7rw7qZmtAf
pllYNlkrZpQ1wGAYN9vj9VndDhczRkmdmx06Cgn2tnVzU1kmAm9xsXKdtSlm64kr4NbQrVy3
7iKdmQmPuJhJXirUedioEcO+ch6boMxltTA/NslU1UGtFt026N+gabxd5dLitz4Q3iNTRHdA
Q7XiaB1sB9GLtn4xb0n3q3jk0THQLPuJjW4FQ0NtL2isrmu4y9vERus6EfjbE4/W42eqrsCV
ugsbq+r6URJaqbuwX3wEO0MT+sMwC2JWSVctRRctLG/2+Tw4g93hYrkUNdXUVOAn1DzT6xCW
1oewO1yytV9Wm1mlzB21F3Jpv1QFtq7UzciER1xMn5VkgcB1lJpBuR2g6vbIqKrTLZp53rDF
e0WqOh6r2vbnJplSbWKDeymVcMebt/Wxw+BGvEleA4t0Exsr5fIh6NTBxMaKudO6DRRzFzZ0
fakfKaNFxAsbu76iChK8/yY2upszJ2yE+YJ6iLm8npCceQn9WY4FiYU+9DKaVR7QmQ2fEt1K
AP3Y5FKZ+zB3iFaqwHYqDsPbKuaWyWSbXMoZ/ZDyUFUHjqLbRS7HruuOupmW8IiLZYy1obfZ
UIVN0kKncPM6cHaTjLDuGPQ74qK/GPyk0mMKl5cpNp+bZIo5ZPbUqrTWwf3Pewr3NzbJa8fo
YEfKxEYfvBbQ1ueCRh+7ZkLDni5stKKr5yEepugMG118rfAAzIWNVnT6PAQV54V1KdAtc6P6
DEvoz0IsqLRWhEu3+ExUO/houps53D0utaTGNiapnEB3T7c53GVq1CaX0s7Wszws8xGdj96r
nPytQLeSQa977OMRF1Nnut/vhe0EBw7AYo9i490Y7h4XkaLPGnOV1A1W7Bgu9fXZ/h4Z3cmV
NKRkXaEM+n2+LfJ+T4u8hpqCTGx4fW408BziwkbX59D92wWN1XKmvkGDvBMaXpsj0M1nYsNr
cwWcEJtYlwa69Vt2RiX0hxEWwpy6WF4UFXQo4suV3B6XyjXxmYPOvaJcnJTcujq3x6UMsyFJ
Z28jmoSzWTb5n0ourY/zZ1DCIy5WnaudpPViAfVw/9xXF+f2uOimR/+2ntPBGezz2R0jeFCc
2yNTeh0pcWtieWRvi7xIJfddFnkV7J2b2Oji3OhoV/+FDS/PNdSG7sJGl+d0twwfuBo2ujzX
OpqBe2Gj77/E6IHwhXURdcsX7phJCeNhgkXl3JsdhiXGc8k8uJS2Oj7+scmlFrHDI8mlw70E
Lp1N1PKyf26TS2nVJiKIqDTQ98PnyDWn8rN77OMRF6u0ZU612t5B7zU4l+yL63ObZEQkUWNb
GeqghZFe5TG2m9NyKmKTjKrT1Fpu3FJtuInJH1mf+xKbPNjDzCW20m1cI9wor6Ee4hMbXcDR
VwtcwDFsuNbsYP7HxIaur+ofwqUSBbfOSToIjWSd2NDPx/VI6GjDxLocBC/Lh2NGOYyHUQ69
qny1MM9eMtxE5mLIvJ7U2OLCh740e0v6+s8DrB7qNR5P+Jvx2y0q5/ht4i42dcLgYKTb+O3q
TPt1i3084qKSsdh4Z2XR26x27B4zIxYPoZmWJepNMqrHZNSu4qxI7mijootbHi/Nbj43yYje
uWXURDSkwHbMb7M8Lz33HSVElWqjYT/CCxp9aqjvI9jqzbDRoq7DFZkLGy3qekULdBc2VtZZ
6xl4Kjyx0bKug+60F9SlfLh+4840h/EwzcESzVPqmQWV+E6TAXeiboeLCjTulubLklU8wB7I
PmfC6/LhDhcbv21MPbGU8ygwcvp2ObAxqXw8onJaIPMgrmJTuPjAhkvBjZc+eZtkVGYPZq7p
HKdBNZ3PkfC6eLjHRXI1ElkFHRwB+bbJ+41t8nRHApupGDb8QLjgNnmGDddzoBy5oLFqrh6C
xjFNbKya44MaWIKd2Fg1147Uwe9vYl303HJaY8zshPEw0aLlOjpZS1lLsPGxSwzu2iRvi4ve
BFIapdJ7P//dmEeej5vKSjZ8blExC+PEuoHKRglso/fxPb5zU5lcPh5xOd1UeLROeaiaAw2c
3NxU1nuGPTLV2uFqL12fiGi7j5dHnix7/DbJFOFeKykXfQDAK1O2yLwF3a9ikpePlEBhMrGx
uk7flhU83JzYWF3XbCME1ukubLSyKw3Nc72w0cquNLCOOLGxyq6rWgOn1CfWQ9ktm+P+GjM6
YTyLtBBKzHxOfI4GzvJ8uVHeFhfzvCPWH3rRfzNa4vUyylt63nxuccmH9Q5WHkksfg38mepF
HgJi2U72usc+HnExkZZbb41Um/QKH1l+tVHeJpkqmTI3aSXRYPQw2cn+eL2B2CNTainJZjgG
EYPdF2//49/UKE/ApsOJjZVz+egCzh1MbKycs6NeUI5MbOj6qoTsjE75XdjoY/WW0EHrCxvd
y0kCendMrIecy6sH+l9jpiaMZ2kWVGyfPmoZGTbp1os85NzN3MYel1qqvmJzt2PXjnLxmdvg
dQ1lj0vpmfWh1dlGHlCZ7TO3sQz1et1jH4+42DBuMZ/gctXr0K4t9tCmulP5yU32lIzwKLX3
XMpoaKuCk1VeXvYGfm6SKV26TdU0Kr3hcRbvaVwHOfdN07gJ3IJc0Oij10ZotOSFjT56JTQq
YmJjNV3XnRZ4uDmxsetbj4HmdU9stKZrAxQOE+uh6dZWeWNmJoxnWRZUOBFZhT09sMrz0XTr
w9c9LrWObta0Q67uNkzTuaTOrq3yNrkU69rK0i3bFDQE9bHKM5vin9xjH4+4mFeKybleS5Yx
4KYtF4cVvumm2yMj5hqaM/UkHXVYcpvFXe8c9sjYkasMtuNk1aeopvszZ3H/dK886WBn/8RG
l+gG3GVyYaNLdAIneF7Y8BJdAp9GExtfokNP1C9seIkOnAa/oC7nreuzsJmZMB5mWRRqLZVq
kaBgMkdAgW6PSy2dh/6OVJmirRheBbq1W94mF6XSqqpT6qOAQfUBBbqZmPCIy1mgsz2DSVM7
Eo8t0P3sJntKRkoiaaWmImj6XUB9bo9L6TVTqpL0l9PGuz4XqeW+qT5HTUBJd2GjX/kFtGy9
oNH1udxRw64LG12fG2hz/8SGt0ii6YcTGy3oxoP63HCqz9X163ZGJoyHURa1cs+pFYaPuMml
VUsl3ara8GOTSzXfv5Qzpw4nrVWPo/C78tweldKstanXNlqDj4+dkizWJeAZmPCIi5ne6baB
TxfDMuD0BxervLvy3B4Z1XFpdC66bxAqcEXrq63y9sgUG4vqJZehKhXXp39keS5/hVUeGkYe
XGxCZYnDo9FB/n6TfZ+gTioTG13PTAmVHxc2Wv4ybMV8YUPXl8mmfsBf54UN/f5EX4AEGuRN
bOjn43ZcHd3YbLBhXSqaq6LGX2PmTIxnORNd34CcuAxVwAOtaA6HIdTbCZIdLmbGl8jmULs+
jcCjdi8Hv7TWvztc8pGbVc3I4lnQWpNe5FLRlPWU0oyZeMRFVZYxMX9lXSC0r3V3BPVvknFd
0dwj0zK3YoGBqhgbaE3h5OC3TjP53CQjrBo+i3l3dtBSaLc8+6vL338aB7+W8Gb5iY1Wdq2A
wy4TG63s+kDLKxc2VtnxkSs4GzyxscqOdM0Y9vAzbKyy68eo4Oz3xLoou6XFGqWZNmH/54m2
G7WzpCuuCmz90It8fF+W2m6TDZsHNulLqsjoA2z1t4s81F1ZHiVussmHjTrTaPp0GBk282OH
yW3Vd8uuiBebj2dsklVrKVOTQZUEDJVMTuXaupwR3qbTuJlLc6UqPMBHqV7lcWxNtJxF36Yj
IkVa4t6kJtDafLdk+5Z5v4CnX83gsOvEhneCod4qExuu7x7Iu3h1pw9bWN0ZNlbdlYMS+Pkm
NlbdjSN1NHjjwrqou+WxNSV6KYhn0RtDxZ2chikJ3bvbRS7qbjlYsslGtyFJVNXVTtVc5EB1
lz2cbE5pvHrjbrExoWZeKbWrtsug63T2sUxJeRn09mLz8YyN6jQVHN2qXbpEAhaJ7SqXkteN
utukoxu2Tp1TEYsUROWQR59E5mUX7+f+6rTeRmKzay4EB/HtNb++1d0vZPCH5kdNbLTIQ0Mh
L2isxGtHRe0RJzZW5NUjMahBJzZW5IllB4P2fhc29PMVOrKANaKJdRF5S1ddSvklJJ5FPqRS
B49qDn8FfFVlH1O8W5G3xcYcvJte0oplzqMa/PAYpNKlWbaOba8NF5YyVBZVEjRI8vAYbFKR
99M77eMZGxUEPKi02nRL0QTWeC4lr7pMWdtmYxsJIt0gZeYKFyQ9epgyL1uUP7fpiP5qVKvm
LKm0Bket/ZF9in+8098A36wTG6vr9G3Z0THiCxur7OSoXMCzrgsbur45HWmgwvjCxq6vfifw
57uw0fsKyWBA+8S6KLulYwclfqmHZ6Ec2Vww9Z3be0FjqPUil+TcZRPhj202tXAVTqT6jgUt
Rno4ClFbaqHPbTb6llX9oC9yVd3o0uy9bP8m7G7qxPzSDg8DIDJxS70zjZHAoXW7ykMKrQ3/
tukI99YLnVqI8NRZn5HipT3M/uoMzo272fbo4qB03kPFHsru20z/wBfsxEZ336UGTu1MbPTp
LI0OJ+gaNlbgkW7x0bHdCxu7vlVfu9hj5oLGfrpygCM9CnQRdjenZeUlHp5lcjA1fZpnK9pV
sD+cXM7+qCyTgH9ss6nFDHYH1STgfGSErtskI0k3fMlMPEoCzdh84lLyOWp1f6N9PGNjxbdS
2Nx7mIhwv2CXkt24KQ5v0rEmtaG6TnLvjeEuNY8pEd2G/exee04nNavcq6rrlFHVvXevvXXd
9xr/NcZ+fBc0ul5XKjjmObHR9TpB650TG12vyw1tVryw4fW6Bp50Tmx0va50NMD5wnrIuqWP
mb5t5aUdnmVAcErUzf64ow3udo1LuW45wrhNppZaW0ujlVHA/nYv7787WbfJRmWdzTCOWjIa
Zu4l6/LN1I68hMPDGIhs1tScCldmXNZ9eb1uk45w092D9E5U4PhZl3JdopvGzt3FGdnsP1lF
KhWwheFdrvu9PQAzVi65oNHFupJA0+mJjS7WsaBP5AsbXazrCR01vrDRxboOq88LG12uawn0
eJxYl6LdqsylL936khDP0iCYLeQ0l5rg6RC76KtPYzfZqBAalgRrgVJg7SGiarfJRtIYuXHr
oooIHWN2qtrdyLv6UhAPEyGE9RY7uYzW4dBWFzMUuakPb9IR6UJ5kLAMgk2RXewAqd8MU+zS
IdXc1pNhx+Xg5M6fWrbjrzAEBO1/XB5GbiMe8dZ7tYHf04WNrukQoQ3PFzZadWb4sOrChq4v
p0OfMNj3N7Gh318ZqiTBRIiJDf18rGuWwfWdWJea4k3PfXspm2exFV3MdG/UoZoA9GXQizw0
9K1ByxYb81pRKTDsLDKD9j56jUs4XF66722SyXrX9FaonnM3BfVnyQ4bAhWdNz2A7SVrHkZX
MA9JrLImWeEXFZ0edHj5u/mxTcfi1JolpNCQCntQu3jw8bLH4nObjmT96ejCcC0Fjam3q/5E
0fnPZMOX0E72iY2u7QxQhF7QaI3XUWeFiY3WeL2AJosTG/r9id5R4FbsgsYqvHZk0Dv7gnro
u3JT6+kvEfEsxKJzrn1IV4nHYEeTXeRSVbw5ydtiY5mQZdhEpcXMgiFr2cdOsNFNVXGTTSbO
UlOy4G30OediOKMC72Yn0V8S4mGQharUXEfm0pnBEwOvXsDlVMSPbTqNyshWu84sVdCpiOax
OpxvegE36QjrJp7FjMl7huW3bD0I3gLvVzDg6+AIwMRGK7uK2i9MbLi2g0ciL2ystss2loOp
kxMaq+z4yAI6qE1stLYrFfW2ubAuZ8bLUC9K46UgnkVnjERm/tFy6gV0PHSLzrhpv99iwwdV
vaIKK5XWMHVnF7mou5uxyi02Vr4rJHaUPyiDytsu8lB35WakaLz0w7OYBh6ZOkkX/UPAfguv
ALlyU77bpKOKzqyIi7SSCGxeTi7tpznRjbrbpKPvn1oTdxm6NmCvvV71tlf2UnffZcCXwED7
iY1uHeMOHsNMbKzIa4dk8Lc/sdEiT3eCoEy5sNEyTwr4sJnYWJnXbcgAPOS+sB4yb9kS9BfR
K6mBnqVo9MI9j17LINRY6HDJOr47o90jw0fSG0GUiNSGn9G6zH3Q2hVtj4zqNSveDSkt9wTm
vdlFLiJvvZ2gV0rDIzZXSnAZQqk3HuBEYYDI26VT7ZHNVEe3mBP0UNNF5J1DQPf32mM6pVHu
2QbAcj03k5jI29r7v0Xe9zrwtUSwA59hY4VdNjEEz3wYNlbYmaseKIwnNnR9aRwNdSg7obGr
azPOYHVsYqN7P7Pg87yGdem9W0980CuigZ7FZ+TKQrmxiEWsov57Lr13NxMfu2wqq56rJNYQ
BbqIeU180Kre9bnNpvTWdWmKlYfQJo/NIcu/nc2unR7pFdDwiI0FYZQ0mHuXNArodeAUn3E3
0LtLR+xGa6laPlqG55NdJnq5rivF26vTW026xyupcu6o7cx7otdD2H2XAV8F9dPERp/Olsbg
G/bCRp/OEvj1XdDQ1c26I0ZzUSY2uixbUd+AiY3Wd4NAR5CJddF36zMzeqUz0BPLfAv1aNKo
lsRUwQl+N323NmzZZVOLFGplJLKh3ljDllWp63ObTWm1ttEL9dEy6hbt4fx0a9hCr3CGR2zM
eoXPgJbemBJeGvI4bL7z4dulI1KyCJHYHVdhg2Wfwt26z3N7dYbN8eRchq4T2Njwjs74PY34
egZfrRMbXbirGTXLuLDRhTsZoJnMxEYX7jqjn+/ChpfuChpNcWGjpR2h0aoT6yLtbk7KXvEM
9DA6o9Go0iwctIJH9HbRV5fuNtlU7pWVEFFisDc8onS3yab0OqwfMpuDxi9TuXuFMzwic1bu
arVZUxJwC+EWe3tz9L9JRrjQMK+WMkYBOxl2hxD+RmftxLe9Nr00ZpJRWTq+Ou/YWwdd9011
uwx2WV/Q6KrdaOi53YWNrtrp5hQu2xk2um7XOvr9Xdjoul1PqOfNhY2+/wjtWpjYrxZ3r4wG
epbRkFsREmYeFXRmjNB2m2RqYX3bUrX2XzS0xsuI76Zst8mmtNaIzSqxonkTXmW75YjIf99o
H8/YmLtJ6l313VAJkQku23noIZX6P7vVHtMRkZqHKtVKmcEKvpMRny7Pz+6156szhugOdEjq
esPBRnx/ZNnuS4z4CH26enje/sZWfBVNG5vY6JoOnO5xQqNFZ4Yrihc2VnSaeSJ61H5hQ78/
c14p4M90YkM/H9dDn86wEZ9hPURnWb1tVAu8EiToWYJEJ5VnNj1iji2wUYtDped+yGOLjZnq
0ZDGjakUwYSNlxPfjVHLHhvzXBFLwaxUK/yscxrlvTssfgVIPGJzpntYQbEx116j0z1upjw2
6TQLO8zNSsk5gRNFTk581G+Kipt0hCwVJ6dhNtADPvt+O/F5qbtvcuIjVA1PbPTBYj1PN7CD
RcNGyzx9bcIyz7Ch68vW5wdafE1srMwjvafAzzex/+vn+y8AAAD//+xdS7LcOJI8UdOA+AIX
kFm/d4qxXs1iuhYz97eJSJLayEg5URD06SyzLvXCWUpPZiYd8XH/gTKvdTC66cDOkHntRuad
SRL1WZJEK1JJhYwMT5JocxxbbmTeEJtQbCEhWrWcwRRFHVumzGt6vWLzOciGttpDtHI8gM0I
LbTHRVM6x9eGy/XMkXjE5mW4XHM+QVysgEMhk4qLxW7q2IN0PM7mcaCgGiJPQWfOuGqKf7Td
FBcH6Wj8AlDPuWAtFY8afvvxTZJ5y/34egGtRg7s6t5d62gK2Y5dru8amhK6Y9fqO95QO75E
rtV2nEazYAlvx67Vdh7PUPD5dGCnaLurR1Q8cc/AhvosS6O7NWmt9RYCHt0pmLKdfOfGN8aG
t6okJeMnmjqYCJAXTdF2N0YtQ2zSc4WVvXEJNmDNa5ZRC91MBZ5xDY/YhEorLiUZaRy169K5
QJabY8QgHZP4UktP70dyQwPp5rjxXebrfY7fHZW4xGshtYrv8w7ReWu7X8WNr2bZAZZ4iV0r
8Xwr4ENph64VeL6pPPDik/VefAUO09ixq0VeHPSx13dg14q8nIdFC3g7dorIu+menaEN9WGg
BoUc4las1SLoesGcQI27At4QmzTWq1SlCWmqiaVufJe+IJ+DbGir3snFpXLa8qEFvCnTgTeW
y/WMbHjEJn31KkkPveXUwbCTaWZ8N8eJQTah7TKbL7478eSDJeskM77vftQe04m7kunWvVCt
4E7A24vv9/Tiy20ydKU3sWtlHW2tggZVB3atsNPNCIz5OrBL72/tm1IFX9+OXd15j6M+6Iay
Y1ePf1YDhd2BnSHs7txazryG+ixLI561Ie1ywivkA7z2MUMK3bq1DLIxcQqVWlIOoV6Tk9xa
+KaiMshGWpwIyJ2IK+gHMs2t5aZ6d6Y1PGKT1bueCwVpbVIdHO2e5sb33Y/aYzrK3V9GlrW+
ZPA6M77bpd7Rm5OJ2PW12lsa+DvwNuP7rc34agHtZA/s6taso6/vwK5uzdYGthcP7NL7SyX+
TrDh84Iur8pW9O7u2NXyrlWC5V1ip9Ttrseh6ExqoGcZGhRCqGVqQtcKrlpOk3fX1ZRRNrkz
qk3Sf8LQudfN5uxXXCcbjLIRr7leUby6wtJ7rJjyTfvv+iBBZ07DIzYp1LqJ5AZs6wLenGn7
FVdfnI9hOmlwFNLbTay+UjpWbvVeHyWG706Xrl3EOr/qgm95t0reLfficzSd6sCuLtx1wb34
Eru6cKdoetuBXV24g22MD+zywh2hhbEdu7xwBxcWd+wUZXcdPE9nVAM9jdEo6ZHGtViBoxom
2SzfPG4H2ZgW7ynutBbYmHhO4e7Gi2+UjTTpVIpkRQU85kwr3F0PeNIZ1PCITSq7/Bpk8ESc
IeCm349O0Rhlo9xa0TwPqaNGRwsKd8M3J510Qndbz39g2f1245ug7H6WGx85nKKR2NUCQF6F
DEwAJHZ14Y4LaDTxgq4u28VDEPRa2LHLC3cKjsUf2NVl44K6LR7YGfLOr7tldCY10MMUjaah
IJo2Y4I3ZmlCGTfk3VX54WOYjWkXb9Zca6+w1fIMsXpbuBtkI3FsMbPuzATOdE0r3N2UiM+c
hkdscvdVtPTerGSmLzy3P2XF9K5wN0hHrRZpytZJCbYn/uF2fMN3p3tT7a1aM2voksifacdH
v70d3yOhAoqUCT+SE9TwzzIJFNCy4MCuLnYWAf1FDuxyLVxB7+IDu7bYWWRzBx3zT/DSd1DT
AhnUmwd26euTssWDAzwt7tgZevgy1T5UyhlvQU9SByyzvtI0omsj8P22Kc3F2yXjMTJZVubK
aiKVBazZ5EVTxhSvl4zH2NAmRrk0belzhw5NxEUz5DDfHLzOeItHbGpIJ+Fm0iqXDgc6j+mt
b/xjbg5eQ2zSCcaqGnsPRSwNHVOc8RwiujxHfg7TUTdPRUzi6FpnXPQuds6Sdz/JJbCg8W0H
drXKcwcrsgd2tcpr4CjgDl2s8XxjQzvuB3itxuNNvMFOMoldq/FkyzgFTOPt2B+t8c6YC3oS
PRAHDPUSikhK/AHW6OOiKS3tO5E3xCaXfkJFeElTPdSsJC6aMqyoN33GITa0WXZLmYvmKDho
qDClghty/zrrhs6Qi0dsQq8xp0d3Cz3c4HGDKYlsha9NAsfYhFwLgaetdMmJENjaeoYXAnG7
TrsZpWNSS+2dmlAt4EJ7GQzveau8X8Ak0AXscB3Y5RNjiq4a79jV8q4TbgKd2LUCr5atwyY3
B3itwLN4VnescHFgVwu8OO2i+s6n5EnUS7+zeOieeRL0xOPfNlUTfZ3cawPfbpvSmKvi1wEM
Y2x449rp5c4b/3TUBHrGb1dolmsT6DE2lM/cXqV6/NvQNMMpeXkhiK4a9F8/aV+esal5kKAu
qtn9BysHdcpBgqpdbxqPsQll0zy0atwWD1qOyjub4tB9uaP/OUxHxTqV+KX3ph3sjmXK3lve
TZJ3P8UnkLaioEo5sKtVXnwaYZWX2LUqzzeDJxV27GKVx5urgTL0AK9VeX0jtIr3gq59demP
AQfOyQy7pXuNd4ZJ0BODf9tEmxNnbGxp4K6ATekFVrkcwvwYZBNyzeKp24jMRcDt6TlG56Hx
brZShtjQ1oxK6SLZQwOHKvKiKRrvSkZ8/aR9ecYm5Fozbq26U9wgdKR0ik9gLd/9pD1kkzkf
9JoHMK5FO9rZnBLnRnfV4kE6VoVzIsCLCcE5Hza0M/TWeD/XKFDBdsAOXavq4htf0QC3HbtW
1f3iNoHctnz8of7FiV17f21DM5526NpXJ1st4K72gZ2h6tqNqjtjJOhZjITEneU4rscDtxEa
IzHmHvHERWaITe6VtOKiEofMii+jzFF1N8sog2xUSKjV3oQZHZWds8563cr8+kn78oxN2VrG
oMRNz9IQg6vTcdWU0OEbP8pROireSrEcAAi5CrvIzLB/Zr0p3Y3SKelnXaRzYQb75pnt+5Z1
f1/W/aRl47jR4GjRjl09elcUPcru2NW92fhZAfXdjl2r7/qWO4yYvtuxa++vb/EzA46U79i1
ry80ueJuN4mdUre76ZidGRL0LENCtKpYCynRC1i3o8Hspm8U3hWbj0E2IdaahoBQUeMODhDV
KQ2zUHg381CDbDQ0t7B2NkND3Org0Ps3Cu/GJ/CMkHjEJrWa167dqJEV2CdwRuGA6M64aJCO
WmvcuZK0SnCIm85YBqfLOuTnOB2WWtkok2TQ6PZ3QO/vaRTYDIzOOrDLS3cdNQrcsatLd+rg
+3dg195f3oTBhvaBXXt/47iAKvcXdHVhsRbUh2fHThF2N5PuZ4YEPTH2p81bKCFu3rh1QQe7
fErp7tLO+mOQTd1aKWmpxzXNAuEYugnLmdVvElNH2Zhrq3Eo8Foc7QKEtp0i7G58ZM4IiUds
ytbj9BofMe6dWWCnkj7DJ5Duev+DdOIEkcchrsFIOuwjM2fq7qYjO0pHNGTda1M7LoXpvKfu
Jgi7n1S64wI6tR3Y1aU7QY3aXtDVhTtmvHCX2LV3t2/xGATV3Y5d+v5xRj2DAZEHdu3rK1sF
p2x26Ax1d9mQ+WflM0KCn9j681aoE8XvueZaD/h2b2VKLG+77paNsalbVyImzh1gRbN14qIp
6u7aFmWUTYu3qJfWOFQRw1p1Ruuv8PVuNp8BEg/ZFBIxftnvvGIIITYzfrWJ5focMcambGYl
Pmk900rcwC9OmbPOzHQ9AzBMh7TErwB7s05wGJ39kVU7/hEmgeDpbMZ41m9sxpezuKgZX2LX
Ck7eKpgnvkOXd4odFEwHdundrYU3qqCT3Ale+g5q2Qq6TnZg10pO3wo4SrFDpxQUb4TAmW3B
TwIH4qwjxBZ6MyvGGJ28ZobitOsizxiZkMKevVUXrfAoYFw0Y/nGy40MGGJD8augTqHOGlsF
HWfiojn1xOuhUz6TLR6xScPszum0Td4dbuJPCVHhS/38McimbLmJXFx7aPPC4L74pAUPtuty
4igdfcUEqzmxgseBd5v49zfiqwbO5B7YtQpPtngkweEPiV2t8RqD2ygHdrHGk3gagKfhE7xa
42kDzxgHdq3Ga5sbWNU+sFMKi1exA/HwPSMu+EnsgG21S9Xeu1AHmwh5zY9WeUNkQrCVEHgS
itUIlKx5zQyRV69n8MfI0MYl253Zw1NBE77joh8t8s54i0dsUq/lqmjIVWPQCLtOWSy6XeId
I5NqrbSca4zrHDWUmqTxar3ReIN0VIndUw3X4hUebXy3jCeJvOU+fEqg9dOBXa3urKLLnjt2
ubozOLTlhV2s7trWO9i52bFrtR1vjk5BHdjV2q518PUd2CkVvJtn7pnXwA+jNEyoiobSMrRp
PMuj5cZmeYwNb7X1fOSq9lB5aAt8ilR9JdNcPXOH2KRQsxY6i6QVgTetecYM3Z0PH59xDY/Y
1JyLKdSaxVG2gseIOqVYfN80HmJTMsTQ9LU8Hl9ukM6kpjGVazugUTriXikddEr8Hzj2752l
MUvd/SwbPrAJtUPXSryMbELdR3fsWonnIXvR+tiOXSvxas6qgVEQJ3ityJNNCpiVcmCXvj6p
W7wv4NTsjp1SwLs20uAzr4GfZWnEL7u3UHqVnRk7u9uk/GC76Z4NseFcsCml5QQaVzCiNi6a
IIuq081k4BCb0Gtp5qvpQCOvfWFM5M2ZDLwReWdcwyM2qdeYxJo5UQdr35NEHunNcWKITcq1
zHQm59K7wbJoisir/Xp3fJSOllq5ZrWzecfXPv7I+OA/3YgvfkswbXJg12q7dBEDB9wO7Fpt
p1v8KONWfIFden+54a/vwK69v/GeMNp837Grxz/jrwTPFjt2irK72hqN5+0Z1cDPohrEyShn
/NNcDLXxlRn2dXK5l/gxyKZm8ETGPXE2ANGkhimVVb/rmA2SkZ5Zb5nj3Qg9hk3Kjr3x4uMz
qOERm7K10rrU1gr16uC2dTr4TZnAuxpp+Bimo+yl5DiDeXUwXrDMcUrkdjPsOUgn1+Bb7Wyl
i4OWTWWwd/5Wdr+AF5/nxBps2JLY1f1Z8CfvhVzdm60NPZvu2LXiLgMnQDeUA7u6MKu9wnYo
iV392SNwYXSHTpF21xYafCY08LOEBiHv8eHz9M0Haw9x0ZR13jtpN8QmZdory1ea5lbiWm13
JR8+h9lIb6WwM3V1RRdgf7y2OwMaHrFJldZ6L6EbOIfWUPUwxWe59puq3SCdOAux9RKsahew
3D3JZ/nab/1znE7RrD+KtEyggaXq22f572u79S58BB7iD+zqqp0RaBB8YFdX7RSsau/Q1bLO
DZMlO3S1qKuKev3u2NUVu+YFfH07doasa9eWt3xGNPCz+AzV4uk30cgMdAKhKQ+nGtrr+lk7
xCZd65zTEq14eqMtdK2rLtcefKNslGuounhAt4IOxw7uMX6j6r77QfvyjEy6JGfUce+5EmTg
rOokb+W79IxROirxWfOWC+fFYUfBKaqOys0JYpCOhOJu8QMQ0k6N3r3YlaruJ1nwEbjuuUNX
10w6g6NOB3Z1zY7hxNsdu/bu1q0XsKxxYNfeX49fQrQhu2NXN4wzVgxtGCd2StXuZp/izGfg
Z9kZas0yJLZ6I3ABiKYkANxmZ4yxSaXWM+utv/QdOs41Jzvjcmb/c5hNfKrFjJpUEVzfzcm8
vdF3ZzrDIzah1Kxx9v3ZzRTeQGhTwib85iQxSCeNr6W+dswLGjM5KzvjzvBxlA61OD1Wa8Ja
8H3ZP9IU5Ye48MFyYMrszrRNj/U+fBV0aTmwq8s65g0exErsat1JjrarduzS+1sLbZ3ASc8T
vPQd1FwsAaNbDuzS18e2aUPrsjt2SmHxZvT+DJDgJ6b+cegh5e5W1K2CZfA0K5+hPO9sWobY
pK+eSCnaSkUz/2Z58cnNduUQGdookzDyzlRygb345ux43BxxzvSIR2zSi8+y8c1G1GEv6yle
fLc+LUNsyuuZ10vN/7GDcyOTfFro8vz5OUxHKW5Pj8MgaxMwbzyv+hN153+UGR9aXTywq8s7
2kGVcmBXy7yGhmm+oItFXjqcgM3PE7xW5NWNHXsS7NC1Es83R40CD+yU4uJ1yUfOFAl5Yu1v
W41f9ZKblQJH2eZFP1jijbEJuaZWrXAvZA4WF+OiGdYzdxpvjE1qPHen4BJKAnRVWKDx5AyR
eMTm5bfs3kN8VBGwbzDLb/ky0PpjkE2otTgbqZeaUq/DI3Q+oxV+vbzyOUxHM8LRVULnKdg0
Gd1deUu8X8GKD83mPbCrW8cZa4S2jhO7XNsp6AV2YBeru5bj5LAVnywu0SpvCru07NjV6i4n
aVB1l9gZ6u4mTEPOxAZ5FqaRU+vxs67UMxUAteKbk6ZxPYU/xoa37OBmpzUeUQVMYuE5WvVW
3Q2xSXUXotszIKQYGHEwS93pdalYzsCGR2zSiq+E8tYiyQZdTZ5RKqbiV1ObH4Ns0opPe9Me
X5zi+C7vFJeWUq87x6N0xMRzRrg3KQb+8JbBJcq3vPuFvPgInHo4sKsHyOK4Dh5rd+xaledb
OmjBbnwyo0L2SOX1LGuCKu+FXavyJO4ZGqaxY9eqvB7CFxxyOrBTanjXy5ZyRjbIszCN7AW6
Vk93EHDL26Yoifsa3hCbbLlWq05dOhewAbGgTzvGJgVbbbWZNuMu4FTKrBrejco7IxsesUnB
ZlRTgHc8vnyS4XK9OU8MsXkZLpcSCi9Uq3df68XXblTeIB1pVdOPz3rt6IP17bj8O3rxta2i
I3gHdq2yoy29VNGt3sSuVXYvfziwPrZjl97f9NdDJ/AO7Oreu6P9qBd09QAouvK+Q6eoumsf
PjmjGuRZVIN4yQftyyHNUBffST5817uWY2zSdyUkUC2izg2cIYqLZmhUv1QOn8NspOUWi5rk
Lgu69jElV+zOrEXOpIZHbNKIj9xVnYyZC7pY0GZ4z9DN+N0oHeU4D9UUQ521wXuwU1qzdFXD
/xymE2QaS+nOvSnYtXvLut/YiC8Um4Hq5MCu7s56AZf/D+zq7mwIXjgoLbFr1V3fcqYHNuML
7Oq6bEW9+F7Q1equN1R87tgp+u7KOj+eumdKgzxLaRAqlSgeuqYKpzTMMGYMfXdTSxlik64t
7JSyqBUFg8Xyohn6jq5jDUbZSLDIpdFm7DCbKbNqt/ruDGl4xCbN+DjkqqpZj7MEWueaZLR8
Vef6GKajRi09gkS7GuxMPGXp+s62ZZSOdO/USvCJjzI4Mv62bfk9zfhyDx0140vs6rJdfKFA
YbdjV5fttKExjzt2ubADq547dO3dta0YOLR4YFcLO1Q47NAZss6uCl3xsD0zGuRZfIZWzxIX
19pQ96PBXbknqm6ITAo0ivOldRGzuljV3VRSBtloCSLduucYFLqBMOZ6+42qu6kPnwENj9ik
WTIZxY9cb+TesCLkJIvlOzO+UToqxhpnh9Cp1RyWQXPM+K59H0fpSOfaNF10akV7Ye/4jN/a
jI/R0coDu7pnFx9D8IG0Y1dX7ZjA/LYDu/b+5rgImty6Y1dX7UjBquKBXV41hut2O3aGwLs0
z4/n7hnUIA9DNNLawcR6nNgJDtGYknx7p/CG2IRYC3HH3fKd6oyxmabwbvqyg2xy2K6zkVBI
CNiOb4okurHjkzOm4RGb0GpSxKhyZasuqCSaEcxILFdF1Y9hOmosSqVXLaWA35xJdTu+3BH5
HKdTSYrWUrq74u6Cv2WIxjr99j9//fuv//vr3//9r3/EO1vKP/7rf/+19DmFPeFXayNQFk34
VZ4gwH+GK6H0rSmYM3RgV1e30EGhHbpafIvg+XWJXXp3tW4OvrwduvTd4xxyQB3lduzS19dl
Q5O7d+gU4X3TMD+jNORJvgFvVaRlfSgfu+BAZF40Q3hfHiM+BtnQVmu2l51ac9RbMS+aIbz1
prQ6xEY3l2rqJrlfqti9yYtmCO+70YwzSeMRm7oVtu7mtRVTcAUpLprBhi5XkD4G2ZTNeloi
1UbdDJQSJX6lptSJr3OJR+9N60zxYQtKqKV3XvM7iu5fq6z6E70INccdwJt9YFfXVltFk8R2
7Fp551s8a8DG+Y5de39pI9TL8cCuvb9tS9sR7P7u2LVn1hafeXDi9cBOmYm8aZ6fcRryJOIg
rfhKiLwMf6topO8k/767qJMxNhl14h5KojtzBUXRrKiTGxvgMTa6Ve/M3JisKbj7GxdNmYm8
k3hnmMbDe1NYtZkGl/ivoymDcyTeTdLJGJs96SS3fimzTjpcWp2RdFLv3AgHb44r6WuLuRQF
rZHyorfImyPy1u5DeBw2GriufmBXqzsjfN01sauLdy6oGcOOXavufGutgj4wO3Zt+c42cVDd
HdjV5bvewfLigZ2h7vqNujszK+RZAIekO7MxF8rkClDdzRiTjefPTVlliA2FHvL0ztYq8exF
3ZlnfLZD3d10zofY6GvSkxoFFTH0yzplDuB+4+WMrHjEJndXPOcaSmeXDi5XTZqNrO1mNnKQ
jlal+Na0LEs6OLk6msABuwh9DtJJQ6DarVlQaWixeNRF6C3vfhE3Qo87WMDljQO7VuVZppuD
P+M7dnUNTwScz3pB12q8tlkFp5wP7FqNR5ui05sHdq3G462g6ZMHdorGuzq6/7PqmVmhzxI4
WHs3tWIhIBvapJ0y6ymXAXgfg2zq1kx7ziFRHDrBkIc6JQ83NN71c3eMjW7MoVklg7yogGx0
kkfzzf6LnpEVj9ikWqu9C1Fu8wjDrjVTRFG9+uJ8DNOJw5G0EHkhpgg8zY9aNH9TXv3uR+0h
m3x+CzcxZXWC7Z74vdP8tyXeaivCzN7C7u8OXSvqaHMFB8cO7FpRp5t3sPR0YJfeXS6bCdg4
PrBr7288bCvqqrtjl74+Iby0fWBnyDq6XnrRM6xCn8U7dClNuTUSuFk2ZY5QLucIP4a5cHwO
WCU+rSGE4PLDnMLdtVXNGJv40JQeRERI+eVOApUhZ8QlUrnZntczqeIRm7K5FOemnYTKa0EI
G1ab0pfVa6uaUTpKnnFt8cVWoQ4X7qZI7u9/1h7Syaa5lE4hudkbbAdQhti8Vd0v4ERIW5x9
waWKHbu6Mwt3Xl7Q1X1ZVjQ/ZMeuFXd1o8ZgSOqOXfv+9Q1c6Hkh1wq7+FkDi9k7dEq17rpP
pmc6hT7Lc+g1FFBzTZsXcGwoL5oh7C77yx/DbKjmRnb3SlwKWnSgKSsVl1Loc5BNGglRqFTJ
R20FpQNNcquxm7rwGU7xiE1KtDRlLhkS1xV2uZsi7OpdYXiQjoSucxNlVdeGDtzNcGeneuNB
OEqneyvcsmgX3x7wFBFXvT2m/76yW+xBmB4J4ATBgV1dsWvgU3+HLq/XwXuyO3Z1vS5OsXC9
LrGr63XewUWeA7u6XtfQdsWBnSLsbppjZ0CFPguoiHeuslr8rDs59nueF00Rdje9sUE23EQ6
U2nx2FV0HnxOxe5SCn0OsqHNs+PWijRhA11d8qIpwu7mCHHGUzxiExKNmkuuURhZB3+646oZ
JS663HL5GKajGcvcOP4VZ4iKFiDnjNrdVeyG6GTxLZO4iUUcnXF+V+x+YxdC2uK8CFfsEru6
YicdbCge2NU1O0WtPA7s6podms2xQ1dX7LyDuYQHdq28K1tTcK30wE6Rd1d9pXjonvkU+iyf
ojWtLTNynTvYJRt1QfhG3l1JiI9hNrX3OCqZ5r6foGxogkFF9UtB9DnIJiP4NG5KxhdzNdgf
csqerN0cJM50ikdsUqjlwKC23ApR2JZ5iryr7eYkMUgnxVAVod47GWM/VSvqdoN0unHvtWTq
ThEwuiGv+hP1HcP67sEjA3xPZyRh/M7We2AbcYeuVZyyFQJHsA7s8i6xo82qHbv27nLoIOxn
f4cuffcsNDhonrZDl7665lspoOf6gZ2iN6/8JUIFnMkZ+izUxDw7xTW+HV5Bo5m4aAYbuSyO
fgyyiS+5edDooTd7Y+zTExdN2eq4VGifg2x04yqNQjeXJgKuOOVFM/Tmjee1nrkZj9jEoauV
yk4WH+MQ56iimVEmuFl1/RikUzdmy653tr3RkMfRVdcHviyjbFwsnbutGcPzFW9blmmy7id5
7wnopL9D16o72zq+tNtX7+zGXwnmj+/QtXeW0usX3NndsWurdekeBhY7D+zau1t40wYm6p3g
GfruxndPz9wMfZJlwFuJl9bYPQSRgLNmcdGceuLN1P0QmxCeViz0qpXOBH7/8qIp+u6Kzecg
G9tSPnj6EMeN75iEyIt+aEPy6yftyzM22Vt09RZqtRT0yz3Jd6/cRBGPsQndmRX40I2hikgd
Tlae8MWhV235/qP2kA5tRUM1es8PHINthbzoLfDmCLz1vnuou/mBXd0r7uhPxIFdre5aAR+W
B3atvvO4Z+DrO7BL3z/3jQs4q3BgF+u7slUCK9sneEr97kbfnfEM+iw6Q9jiedFLryKghoiL
pizwXlYjPwbZyKa9V6+tUTFRcAtnszn94puH7hAbfeWoK0ltIVlBhycdbOE9cN7TM57hEZt0
3jOuvXHrXQvoDDHLlaXdlIqH6ITy7FmKdC3NCR38nnIwiptzU78bZCNxhFBLfdc6aM4UFw3d
m7e++3WM9wh9ih3YtTLPN+oNlHk7dq0MSDc9cMv4wK6VeW3TBv7QHtjVZTxHZfKBXSzzeibG
gDf4AE+ReTdLlmdEgz6Lz2B1ZUr3wtYFLePNMd/rN6P4Q2xos9qlN5FKpLCzyYx9tZB51/EZ
Y2xso7g1JuKNDN1wi4vm9DVvxgLPhIZHbFKwkfaqNUNwCd5/nSLzXi6t9x+1x3RM0hkxbR5D
54EPo7xqxt2hm62PITp1U3ZRa90yjQ+OwX4bLP/9rY/l7nui6Al4x67VdvlIQkt4O3bts183
62h0xo5den/TaLqi+7I7dun7x5yef5h0OrBrX1/fWgNtlQ/sFGV34793xjPoM8t8L62YceHu
DA481ikub/U1/XH1uB1iQ1v677n36mxU4ezbGeVIt+vojFE2KsUpPttxaxy0VabBp+03Cx83
q0VnOMMjNilqzHMVh3N/HLRHjKsm+M3f1CM/hum0Ws3jCFE4VDccnTFjFOd+4WOQTjcqqj1E
arACFyn/1IWP/xALPmJwSOvArh7AK4Z68O3Y1U1auMl4YJfe3zTWK2gwxY5dXZ0tsALdsWur
i7aB+7wBnKLtrltmdsYy2DOv/J5DNyGIenrXoaf1OSZ8ft0xG2VjasxmtbYSz12QzaThu+sc
gzE2tDXReESrdPMOm/C1KWLostX89ZP25RmbXMttHnpeVKwzOLk6yYSvXJZUP4bpGHd1DZ1a
PI5uS6t29XKY8HOQTraNm5FSz4wWcGOxDg56vqXdz/Xgiy8hXrXrq6PQeBN3uGqX2OVVO7C7
tUNX1+wyrhFVxIldXrMz1ENmx66u2XVFa4o7doquu15ltDOZwZ655VvXSk1Lqb2CzhlZ6JtS
s7veZBxjQ1vVeI9U4llbumEZIHnRFF133SEbZaPBxF/7zERgokle9EOF0NdP2pdnbFIItdCo
oejiv+54zW7OVsV1zW6UTqu1akghifcKdDNdULIbZdONemnN43vj6ALPu2T3e3vwoQNjB3at
vNOte8cOfwd2dclO4ILdjBn1ZwbLHV04PrCry3VSwGHPA7t6GLAr2JA9sFPE3XWbzM50BnuW
NZEOfMyt9hB5qGHkLAe+60i0UTZm1qxy5ZZ/okW7OY4oN0/cITa0edyTRtKq559o0W7Kxuxl
e/nrJ+3LMzZZtKsZziDEhSvYX57kwHfdX/4YpmPiJZS3mFftYOdjVn/5ckHkc5BOzc35kj7w
bqWCowyjCyK/urj7IQZ8aCr6nET0aase6y340FXeA7t8DrCA++Qv6PIesYL12AO7VnRKPNHA
ILkDu/T9s74pg+f0A7v29cV7AroZ7NApkvOqAhdC4MyNsGe5EZWscVMnIUFNj7Y6QQdULddh
bWNsZKN4bpqW+LJLB8u9edEMyenXYW1jbDiXeLsWCg1AaAGOJy3xXna9v37SvjxjU3LQuWVu
LTuXAvYyypTSNcUH4nsftYd0alpXOXE3agXdF8+LZrDxm9L1IJvcgGxdtHd7GTBibN5t4lnK
7ie58Cla1zmwawWebB0dYzuwqyVeJ/CH7MCuFfC8tYqaaO/Ype+fl6052DQ+sEtfX8scV7Dm
fmCniLxrfzQ70yPsWXqEtmZp8p3+xA214Jrhul31svf1MchGttqyesVZjXPGSldx0Qw27jd1
xUE23oOOdw/ZimYsTSor3hgt2xkd8YhMfEfNlTMdTKoIvsE7Iwnj2trkY5BOzVYGh/r2kOHo
xmFeNGUU8KaqOMjGSgvtmGk4RcAMmbhoqAP+1ni/gBFfnE8w8XRgV4s7d9Ag48CuFncNzTQ+
sKsHAipqHnVg14q7tmll0Ahyx66u31ED+3gHdoKAoMuaVzxzz6gGexajoSUD2yStJpqhya86
ZyLw2oZvjI1sZi1DtDpJ2sWiNnxTmsZ+Hds2xobT0aR3qlVc0FRenuRbdznf+PWT9uUZmxIn
ArdWiLtrCAlU3c3wSLxZjfgYpJNJllK6x+2RB4YmdU7Gyc2ix+DN6ZVIapyKjA1ckSqDC19v
dffr2PAp+it5YNeKPNtUQRFwYNeKPN/EwK7XgV1boaVNwKHKHbpWQvkWDzdQQu3YtXe3hM5x
8AWe4BkVvJssDTvzGuxhlkYxUo7XJ8pgmSgumrHOq+VmFn+QTevcKnnphUEPPp4z5uiXu8mf
g2R0ay5VW1UKjQc6Zk6qeN0k89oZ1vCITE74sXDp0ksVAYurk+YC+fsftMd0gkg352K1txB7
qCqa4ztzUyseolM3Ya7xpYmDXkWHNfKit8b720sf6y34BAzDO7BrdR1tJuCq/4Fd++TXzQg0
uDmwS+9vvieg4doOXfruMW+Ohn4e2LWvj0IOgSM3B3ZK6e7aWtnOlAZ7aJ2v9EoC8NYMHMLP
i6aouhuTliE2uZfbJXcrieUVF4yNEk4xafGbesogmyK5HWHc49ergkMog7FV38x33ZwfzpCG
R2zKpuKq0ipzV31Fb/8/AAAA///sfcuSJDmO5BcNhQBIgPyBENmIz5jdwx52+rD7/7KAGy0P
U2JWaiwGM6rLu1sq+6DMcjjNjUo8VBEitGY2+W6YdzKc4D9O7HJVv5PDmjNLpnmvw/maDseM
hV81ZnKuCrdGTl0i3sTuRwjwZXRg8QXdXZplQ195B3Z3aZZRD7KB3cvuzI9CUAB6YPfypxqV
HIw+vaB7P12LTjpQSubALmF3NxJ8pzmDPhPM9/OJrfWWK1W832ZFKbPmm2rZVDRO1FoXZ0K5
s+SC9hCu6brjG3Y3GY3UyAn16ntEoDBALFrC7m7uEac1w6NoXvLKZBK1zOo/B2xzlskrXyt5
z4bTivbGXcWkgbf4vEgf8a4wOxlNz12s+LsgxDgFkwV6V2b/phJ8DeRNA7s7a2do8Whgt2ft
0Gn3F3R7zg4dWxvY7Vk7ARsqB3Z71s5AcfmBXVGL5Rted1oz6DPbjFJalsxOIfpLy+KHZO2m
ookEXEhNlK69ogPNy7J21763s9HkWlorYloyod3Fq7J2f/qkfTyLJrJ2pRfWTCKCXtnyIheQ
u6zdZDiNhHoWlRxk6Mck7SajMRNhZtMw4QOlON9Ju7+1BB/cLDawu9N21hRO2wV2d9quoImd
gd2dtmsFleM/sHsJVEmKShi/oFs/XQmpBgIHGA/sCnp3o7BspzuDPfSa6EqiLNlqYZTerVFY
btd2BnPROFMjrqzWrfUK+4ituFo5vbv2u52NpvitoOeqFq37qMfbCmUgp3fXzXZ2ejM8iiYS
cLWpb0yOeUywTTovsTW5pXez4TTSFinI3HpXOJw19r2X6fuv6XB6bbVotlKjURUN599TYpm/
Q4UPHFzYPLOA9lWuuAEv4MK/SRnQ31qoMKCt6Nx+6DTCaE3nwG7nwQ3MTQzs1t0l/1LgCuwJ
3s2EW8O1CwO79fN186cKbOMZ2CUl7BuGcjpa2BObAf9oVo3EmuRot8LmzJbwrXsuPBVN0Fql
7mw4l4paQMTk/BIufO0QPBdNTZ1yqzGlISUzxuzrEoc/58JXVdJfT9rH070p5i86/5qEM8Oe
eGXFGA23a3HAuWjiehutieKMuGdUo2iV1uHdtWsqHAohSvNYqBV+YCb5b8mE/1HqgGA28YDu
JXk1tYxayB7YvSTPUu6oNuCB3UzyShJ49HmA9+5wT1TQHT6we0leZGLALs+BXULybo7e09nC
nrgNWIrB1eoEL4y+QL33WLSknn0tIDMXTWRii5++Jv5P1FRnUfrWLudxvyajqUmyqNXWqnID
3TPrpC7vH3jEtVWwnb4Wj6JxvlY791KolpLBIZQopK0geTem1HPR+Jln6nSIVfxB44Y29q0Y
RuPcroeL58Lx34DvjXWrOceMEPrD+bc0HflHyAMqgSmUgd3N71RwfhfY3Uk8q2AOYWD38jux
0KwDz78B3pvE06SoAN/A7t3hHJ1UYLvsCV7C8G7O3dNIwp6o+7dEXcIGPueuHZw7a2tmN+4m
UeaieU2iGHHoJjPqVbBqEkWvOxbnotGUM5H2RiWzgFWLWPStmaJfT9rHs2goObsTija/ag20
pY1FC6J5mfLdP2kPo/GfNIUTuJQe8/lwRXvFVf5WPmZ2cwr7a6BVKayo/EQsejO8RQzvN0kE
shh4qz+we4meplYKSPQO7O5EXhG0y//Abid6fnKATHSA9xI9TrC78Qu6N43Xkilo8jGwS0je
zdF7GknYE3l/S6220smPXyOD03grSL+TvJta7VQ0YYVsZqX3mH8AlZMXWSG/tICvTt6paPx+
qqWqmLOIzODLpC5q9LsjeaeRxMO96c5UrbbsjxuD+o2xaEWfH//pk/YwmpyKX4xqF6Xut7iM
pvGWZCWvfem+pjdHmpZGMT3dC5jgmfWle5O836wRCNrfHtC9tI6TNbDBc2D30roaGlLgz+PA
7q2+l9RBDbUDund343xGJ8kP7NbPVyS6o2Dnu8AuIXU3wyingYQ9M5AoZpW1kR9NBpp7yKoG
vCsDic/JaOJsKrllEXKmWtAS04rrCpnepFOmovGXlmntMZxr/gc6jLLC5ptf6pf3T9rH473h
RtWy+b5nsNLsi1YIP3O9yRFPRRM5uFDUDMWiLA1MefuqFeG8Ktv3j9rjzcnRsyr11aeBeg3P
aQK/Od2PkAckUKz8gO4uzWY0wTCwu0uzgo6fDexealeToe3nA7v3++upC3oCHNi95I6csIEZ
u4FdQu5ujtzTOcKe2WD4pay9FGx7FrCD3xetMfW4Vm2biyb8j5s0o0rdCCZ3SwxXzK725msy
Gk5V/YzumZWECLZMXpIUuiN3p3HEw70RLtz9SWuKXttizZKq7E3f3VQw4VUqoTNu3W8RneCE
3YpZEboUgf+aDscv7zUzlR7jFWjD6lwDwJvc/WZ5wIImJQ7s7pRdBxPGB3R3ws7v8CArObDb
E3aoZcvAbk/ZCWjqMbDbU3ZVQP2YA/vdKbvTOMKeiPlH9q02ElbuBZ0A8kUrKpelX51On5PR
RPat5m711Z9WsLN2tpz0JGU3FU1k35rl1hvV0hWLhid73J+wutM24unecLWWueWOllp2ZOym
gomMXXgLF9PGnBmepvj2jN3k3mTNzreLf1OVwOTwO2X3txYHRLt3D+julF3cmNCUXWB3p+xK
w1N2gd2dsutg3v2Abk/YKSg3MrC7E3bcQeo+sN+dsDtdI+yJlL84rwlvsxChywImhWQNGSr9
RqRiKppI2BGb+tPQtMDt4LxGGvDmwJ2KhlPNpTc1KyYCStXEou+mdqdpxMO9EQ4BkdYti4BD
UssydlfRfE5GE7k3qixGHhMR+CLdkbGbDMfvQyTa40GjDF6KfNXUqfDTyZ18hzIgSFVWsJS/
sQZfA0foD+hewimpdzDZ9IJurxCjxkIDu3VvO4VpHfb1DezW7081KYNazwO79fM1f+DR29jA
LiGcV6TGacBpZ2FPPAZqqtpbZT+fYggCTC6nukKapfSbwt1UNCVl1ewcrfqxiY6k+aIV0dil
xtvX9N6Uxq1W355StGH0ua7Sor7JWp9uFo+ieSX8pZrmViImdN5mSfZNbgjnZDTBzLpm4864
9eKKisK9Msvs3mQybTG6W2D1vfYuEK/idb9Jfa8w6HE/sHsJnqYOTp8c0N0Erxs4VDywW3eX
mJz0gkfgCd6bs6uJFUw8DOzeHc4WknrgFg/wCpJHV0Tif1A7TS3aE6MBS9TslRzx/zKYJrVV
6izXR+9cNOxfdEj1aHOSUkDlW17jemw3R+9cNH73K9x75EmNCHQ91kVE4kZ/r52WFg/3plCX
4rtTS+aG5khXvBtvjHU/J6PJqXXflR414+a3FYyBhx3vkqzi9X1idnNIKmkoNFHTgo4Tzd2s
3zTvB+jvFbBn44Durhd30NHwgO5md9bAbMjA7mV3h5zeE+m9rd+fWRK0G2BgN3O7kjKYURnY
Jczuij34eXtaNLQnuvktUcjFqHb/Cq1iAfmiJdO7/VpZeS6akjRb79WvmiYdFL72RUvqxZfa
bl+T0agT6B4nrr8dOIMDopr4u3X32unQ8CiakNDrLytacd6NNtKkFaoBTHfMbjKa3CMNGc2A
TrrR6jct2Ru5ds+YjaaY+a+/9uzEDnzSaDJR/CZ2P0h2L4M9WQO7l+GFgj867XFg93IA88sq
mOt+QTczvJIaKgp4YHdn7wweNTqwe3eXJBJy2Pd3YJcwvCsW4efu6c/QnnlnmF/NxPmdNOkd
6wSKRUtyd9f6LHPRcFJWP9xCQTAL2r6RdEER0GnYtXfGXDQaEwWRqOGiIXoLMrw1AwWXA8m/
nrSPZ9GEtqE/YSxmWRvvFERkoWvRvbloctLC4k9bzL1rAetcsWoJYf3TR+3x5tSu4rSeo2MT
dAIhv0+9Kd5fnvbYLronFZ3zOLC7++6kgDWkgd178Nekht7oDuze/ZXkryR4CjWwW78/cS6E
DmkP7F7iGW3OWKLrgC6gDlSu++7aacrQnllMWCk9v3Tynd7B0m5LaN1lgflzOpqYHslh/5Gb
GlqSpQXJIad1V8mhr+lolEqOmeRQuwYH7nlJGvJmTvTXk/bxLBpK2YMxzV2KlY5Ks6z4VXOW
a8OMuWhy6KRGpjtTfqW8QFq34jVwO+gxG07v/pxlE8oRFnZfjVVvXvfXed1vmuLNBT3+D+zu
rrtcUXp3YHdXZoVA9+6B3dtVWVIntKvywO7OyuYCdt0N7F56Z6llkH4O7AqCdylr4sfuacjQ
nqjk+81H/ZQSbVSrgIlSX7RksOLGiXQuGkpanbBqKVKqEDrJu8JegkyuzTLmouHUuefWVYkr
2oSS+hodkJu03WnH8HBr5EW8SzbOhvas+ItxSRLyWg1oLppIwInUytaLMPqiX5S2ux6v+pre
nJjirdpNzS966O/m3XK3gN5tl95TtKAxsLvTdgXmdQd2e9oOHad4QXez9q5gv93Abk/aCSi7
OrB7WR2lzOD2Dux3p+1OR4b20JGhWKZSYjIzM9rfbisSXaXfTFJMRkM1R3+aU9UuMBFalLa7
9rmdjUaZ/bCVbB4VqJkRi747bXcaMjyKxn8Efnclp929UVZYtHfNuOxN2m4qmuwXNWuFi78Z
C3Wwr2VH2m4ynNfMvGY14cyg5uk7bfe3Ft8roJrnAd1L7moKG0t4mqKvsMN+KL6HkuOB3Zu0
q4k7mrQ7sLuTdgU14B3Y3Um7AiqQHtDvTtmdjgztmVuGqFThkp1CgGW/WLMkY3dtljEXTCTf
GknR0lrJsIXqminZu4zdVDScWnNqZ+wUr6I/hDWtaflSSPDXc/bxdGskMxOJaOeGqmr6ou/O
2E1FE7m36rchEjY2AW24fdWKyZDbjN3k5hCZxcRvloYqZPmiqVvET2d236K8R+iACq+YUls2
47Fde89gQdsDu70LkMEpsIHdXiZuqJfHgd26vxqdmwbOBB7Yrd+f9lQFPGgHdu/n05QZPGsG
dsHLhOmqsOpc4PSLaM+8PKxUZclCbKhcj6xJKNZLhYnPyWhK4lKcA5hWbYzeCNKKFheydjNW
ORmNXwSc1ZTSnHOCvVllUQruUk3w15P28SwaSuxv4eyMSWphMJcRi5YkFG9Y52Q00rVma6Qx
54FOvH6vFvfXfDBcu18GilWzhk7ezPms/HTO+U/S31NCTVoP7F6KV1LPCt61D+xuitcL4wp8
ZYUR6DOJ5YJSqIHd+v1ZVDHAQZmB3fr5miSuYGllYJdQvKtxAj94T9+I9kTMv8ZR1bKzu6zc
K9axXpecVU7xbg7eqWhKota7Sg3OamD/fVmjJWjtJq84GU2nuPu1opk7OnXni5ZQvJsE9mkb
8SiakOTVomLM2UTgCd4l0dxRvMlowg+wt2bSioGWHos4Hl1WwL+mo1G/GnXSQi/HFTQf/+4E
XMTxtovvVbCL/YDupnaGelO+oLuJnXWQGA/s1r1tnMwqtrkDu5fYtVQFJO4Duzt3R+Bv44Au
oXU3UrenO0N75jURxTthNc5koPhHWTJFcC+9NxmNmnI9dAQzKNzri1ZQbrMbpdupaMS/5tpb
plakMGho4IvWuDPcSACd7gyPoqFEVnJl/6FmVpg6rBCsupfem42GpDs7VSJ/2lCSSmtI6s2s
+FQ0fi8Wq509FKlOutF5lblH7c3rfo72XmlYseaA7qV3mirawDSwewmepQIayx3QrXtLxCmj
ftoHdi99Mmce2HvmgO7d2+yUraBNTQO8oh2wXBO8fjoz9GfODIVaZT+pTK2AeTtd4mVANV93
4M9FI6n1SNgZt1zQYqYsaaEj0+tjd3ZvIp9aKERApBGqvLciQ8yZrxsC+2nM8CgaSlWdRIjW
GC6CGwJXmPCx/PmT9jAaJzc1RqRyK1QVrYDkNVLRd+LKs5tTmv9guFvjXCu6OW9x5QWjHtuV
92oFf30Du5fWhRAqOOA/sHuP/hqDpfAI74py54PdFUrWsUP8gG797kSSGeh4MLB7Px+niqo+
DuwKUsfXahn9NGXoT6Tyna6LUGvSLISIwUGCFS1dzumuVVlmg6Hae9VKGvO04PxXWtIKae26
C2p6a1ruufptWQWWKljE6S7rfb8etI9n0eRkof8TJhNV8LyQreB0d/O7s9FEkZy4sl8dKtim
umh89zqar/m9aZLVHzQnqLmjontzLdhvSvcjRPeog932A7u7HssFHWs7sLsrsvzA7JZ3m90W
SdLBfOzA7mVPTndflRSEPR3YvZ+vx4QEyO4O7JKa7LVJVT8NGfpDewlVIzI2P33BB3aRNeyr
3ePq0J2MJoiqhAZxMcLlWda02l0PVs5GI91MpImKOc0Do1nTsi83yeHTj+FRNKFR5NxOS+2N
ULn+ZfIs18Pic9E4UyvSNZyInatm8Jocq765KDsbToxScNSX/XqE+njGqjfB+8sEb7vsXgUJ
/AHdnbEzdNx5YLdn7DJYKB7Y3Tm7xgUcijyw27N2ivKmA7s9a8dgyWJgl/C6q/PJT9vTkaE/
c2TI/ib3xy9TRWUOeYmFAdVLz97P6WBIS+7qX7blBs4u7sjazW5NK01blawd7YrdkbU7/Rge
RfPK2nkgYballcA2ix1pu8lwGpE/aM1/NJkarFP3/Xm72d1p1KOX109Kv+ehvO6duFvB635T
4o5BXbYDujttZwWU5hzY3Wm7kvFBisDu3d2aKjiAekD3kqcS5mbYtzewWz+f32dMwKdvYJf0
2d10P51uDP2ZG4OZdbXChRSvYq5I0VO5FA35nI6GwqBKnAplFkaN3Va0t5Pp9XzsbDS1+K50
/8/L5BaMZsXAE+dLv95fT9rHs2govUSIQwSldFSpjlZx1Zvq/1Q0TtM4d261OR/KAv5wYtWC
cO40lWfD6c1UKURdWiZFc5D/nprK/LdX3nvEU0CKsuAduYAK/y49QNhe5MDupcKSCoGZpoHd
ToUV7AAY2K37yy34N7jBJ3h3DbuhNmYv6NZP10vyIwl7jwzskkznTX/iaWLRH9k+WJLOFI4P
L5MRdEhKVhR9X013VxxlKhx+ja5qbr3UDltyrJhcJavXBiNzwdRkVNiaWViUCVZ1ikVLyPC1
LFE/PSyeRuPMUamYE2ICm2d80YLfDb9Mle8ftIfRZP+au7UaTZfsFxbsUfNVS9xf7CarPhUO
pdbJHzThriygzi5NTmv9dC78T1IEjNs2qggY2L0kz891tI1tYPeSPEsEX+sP7F6SZ5aYYfPd
A7yX5EVPD+hOPbBbP59qnMGw7HNgl9C8m5zn6WfRH7kMaKLGbCQ1KlrgLHwsWkLzblJRc+GE
D7NwmFrUVtHZeV+0guf1a/WYuWhi6tkfbI+m54oKz60ZlXaed9OpeBpaPIqmptI1sxCL2euv
h3heXdF3yZcc/HMymtDBpVLMGV5XbWAvSKxasTk3ys9z4YTyMytly/4ysAIrP78bFRfxvO2q
gFYJlgUM7G6Ch07w8qIJ3oe6gBW9Cx3YvfSuU0JbwQd2L7lrft1FC9oHdm8OLyfYd21gV5A7
vnZa6KdvRH8k528puq2cOYjWDH7hr0VLyN3NGMpUOJyEiDo3Z6y1o/oDvmhJEu/mxJ2KpiYx
pS6RW7GGej6mFa86/z3dDDydzhGPoimJOGsjo9z8GoG9e8qkW9kfsl7X9jFz0WR/JRpbV+7N
GStYrvFVS5RjLn3+vibDocQmfoMofpvQBls481T2+03ufo40oKCV2oHdy/E0hr1gccDA7k7i
ldLhwldgN7M8f+EwSOJP8F6eF3ki8Bsc2K2fzwQ3RhnYJTzv2m6hn+YR/ZGkvyYtvdZCUhiU
TI41S7zbLvWsPyejYSfU0q2YtNy1wdI4S2q1l17OX5PRlBQlUxHlUhStqfiiNbXam/mn0zzi
YTTZWNT/0TuhCYSyZG9Y6g3Nm4om/A6C5nFRLc7D0RxeXTOVctMWMBVOjIJ3qVw8IiXYi25u
FPxN836vQKAwKjNyYPdSu2ilB3u0BnYvtYv2EQW1Eg7s1v0NOWIBUwIDu3t/SdHx1wO79fMV
DlFM8HQ6sEuI3c0U6Gkf0Z+I+muY8jYtGoefgB5nusiU91IU53MymrDE0lxFrIf6CipVUpbk
7/rNDOhUNJzUOVATZxBNpaHzNbZERuZyevrXk/bxNJrq/MfYaUPhDGri8yLl5xvHtrlocngJ
SRdt/qxxA4ef8qJxoXqTv5sK50XsYkS/ZPN/oF0Nb2K3gtj9pmnjXMAX5MDuLs8S2v00sLsL
tFLR1N2B3czvJFWwSDKwe/c3x78SzLwc2L2JxRjcAcVfB3YBh7hx9uA83CPi/zzhdyJc/K5e
ai5oYUYn/db/wO8uxdsmo6HQPegU09NcawbzkImX6MnYpXbbZDTxWmUruZiGogzK71Zo/XC+
jObXk/bxNJqiIXvonNUZHlo6X/Ha5nw9zDMZTE6l9ea3oqxVWgc9ZHzVksbIazWZ6XDCOTQa
cNl/lKhaaKx687u/zO+2qwSWAmqwD+zuxE7M+6CJncBuT9yhUiMDu5nYWRJQMWBg9+6v+HEL
D0fzZl+ZIqE4Df46Duz3pu387DqpwxNZf02N2VlDqCVXtBCjS/Qw/N93lRr6nIzGX0PWmGKu
QpUNzT6suBI4b7+sx05GE9UGKqX3Xqufthh14EW6etdpuzOaj6fR1O4kqFDX2gztBUkrjCxZ
rh15J6Pxm6TfhbpToSrSpaKyenUJTb1O202GQynXKJb7j6c6uQPLOb7oTev+Oq37TWm7ouBT
O7C703aloWYEB3Z32q4yyu4O7GZ2V/G69gnezd+LgWKxA7s3cVec5cBKhm2F/NN92o5PDvFE
1l+ThBCdVfNjt6NTwKvGKq6Oqc/JaCjy3+ZxUKOaQQtbX7QkbdevJoC/JqPhRNE+mGvurRSD
lV7W9Ntdjmef0Xw8jab0bP6eI9Jq6EjXmkQX1xt+NxVNtCB3av60aSEBJ4CjlvvdabvJaJrz
waLUWic/i1Cll7lr3k/nd/IdOoFgC8+S7p1lwx7b9fiaP3yoHl9gd2ec/KhEM059TkTzLxWK
0b7fgd26u+wsSApYKT7BW79B1dQVF0IJ7NbP18MtBrxTDOySnOKlZLCfRCeveWI5QL63L+dT
LoULONb1WrSCdF6OJn9OhlNSjhJebuK8M6Pvr5SXWMrZDemciqYmj4MKVSml5IylSOsi17JL
2Zlfj9rH072xnFvR3As7WcNoWlnU2Sg36eupaPymUoT92uS/bM6gyn8sWlLHv+qh/ZqOpvvz
26oKZw8LHeV9G8otY3e/S48PNSIf2L0kT1NTkOS9oLtJXq+4+0hgt+6uZE21w2J3B3hvYdaJ
kYEfcGD37jCxP/SoqPwAL6F5N31a5WQSj5whmhMj7qyirYuAOlxtiTWE07zLRvzJcGJIQsxK
dmLkBxfaRLfiBUHWb1oCp6LR5MduzdX5t/8BEqNYtITmXU6Nn9F8PI0mmxO9ni2TR4NmsReZ
kNzkFqeiyan7xlgz9ftRN3A40letSPzS5XXvazIcDslV59+ZjQo8Spn4PfKxiOdt1+PTAhrn
DOxugofqhx3Q3QTPFGx+Gdi9WbwexXTUUGyAt36DZqkx2Hk3sJsJXkmk6HV3gJcQvJvacT05
xENfDfU3ux8ZRE1QwWVbQiKo9Euxlslwir+LJGePhbhVsBM/Fi0heJcKGpPRaNjUZj91xbKi
AvO6yKX2ckL516P28XRvqLHWGiM5TUFdoLJE2pvpjuBNRUMvr5ws7D8btoy2KdCKrCRdeuZ9
TUejVHsvjaSKVLSpdq4h+83vfpAkHzhJdkD3kjxLaPfdAd1LASwVVBLlBd2bw6P+wKR3gPfm
8DRVQ116D+ze/eWcnBehxpAHeAnFu9TC5awni3ikpd9CqNhf7jVTbg08qdqiUm2+KaBNhcNJ
1Xp4c0U3O0jxfNEaPb6bAtpUNJo6F7NeLETsDM3hrRAIcIp30xWgJ414Ek2J2Zzsr2LnrAQa
wZUlozksl221n5PB5KSVC/ktIteONqLmJTKWfh27uUtMRUOR+pYW89Y5ho1Qhvce6v3r0x/b
1fgYu8e/kLvb70TAxM7A7j31o1oI2rkP7Na9bRpu4FgiYGC3fn8iyQqokTuwe1lnDIlnWMko
sCs4Xb5pxLeTNjxza6ilWW/sBxQbbLm6whCAXt1+VyftVDScKGplyo07oY9PLFpB6e5Geiej
Mamdauncq4GUzhet6b676QCwkzc83JusVrhW1jAI2TrAcjkk8TkZjV/TyESdzVVlBT11Zmck
nkz0TkUTmnrNau89CzE4SUmTmkBvTvcjhPgYbG4/oNursgWV4T2wu+uywqBM28Bu3d3oBBMG
p+pO8PbGSlQIcmD30rueuIF3nxd0ScLu0tWAczsJxBPhfP/iLMZfW29ZGRRq8EUr0o9Fb8jd
VDSUtJRcc1X/uxs4jECrSrJXe/M1GY2kcLCrUpk8LMGSQr5oTb7upvrfTgLxzNtEa3NGVDI3
IfBeFAnYFSmufJOwm4omJ5VasvbsXKgpmGbISx41/6Q3A71T4VAiVaMSwy+saN4+0dsm7a+z
u/0yfAL2Yw3s7qxdAcfjD+j2nF1FJxAP7N6cnYXVGfYyGtjtOTtroC3agd1L6vyRQi+3A7uE
1t2Io/WTOjyRza/Jz9qeOzUqRmDHUF0ijnafs5uKJtJvlvPLsMoaqDEZ3ivfnbObjMai/Oos
qDh7INg9Y4kM313Orp/M4eHexMg3O00tCt/IN+TspqKJnF0NaZNexPx/qE7L9yftpsKJ/Jv1
bup/NRF4rL5l+P7eMnzoPNPAbk/bMdjoNLC703ZoTiyQ21N2jNponuDdXZSo9cgB3Z2wI9hZ
5sAu4XbX9Vg63RnomXNG4zCs6kLN/4RTdkumKNr1mOxcNJTUnAlVZ42vP9GU3RKJ5ZuU3Vw0
nHrrXK3nMDMAe3Z90RJ3hpuUHZ3uDA+j0aKam9BLUhBuf1zRlfZy6rh/0h5GE+1yWbPFoVcE
9UVbEgzfDFHMBUN+JfIfTM7Nqr8N0J/N3IHw05ndtwjwEdyPveJVtGy4Y7sEn6GtDQO7O5uI
FukO6PYisaBevAd2L+P0Levo4MQJ3voNak+KFi1f0L2friVFBd4GdgXjlGtVNDqNI+iJmr+T
4ZYrWbT/+dmJ/Z76kmlKZx7X+ntz0ZTEGqK15WVfa2AJf5FX26WUydd0NNS7WDbJ0tHbgEez
RLHuckTl15P28SyaKHn7I8atFioVzPTGoiXZxJu7zVQ0McfYc23aJTOjA+9LxNI9mqvfzdd8
NJF85wiJQJEZXzP1EvjpjPMfJb+XwSGFgd1L8EoCH8UXcje962BjyAHdurMcNiKgytrAbv32
jBILWCoe2K2fr7VkFax3DewScnethUanawQ98sDgZK1ZEc6NYAsanrTg/AO7uzlzp8IJamNC
oTAh0ipW+fZFKwaQ7bLy/TUZTU1cOBoaayW/vYAyqGmFBqWzu+tmUzptI57uTa8xdyMlOhrB
VHySNXzoT5+0h9E4USNhrWq+QQW004tFKxoaL6P5mo7GNLcSNxRCBW1jzZvdrWF320X3DHQp
P6C7SR06yhbI3aSuweLjB3Zvzk45gaYZB3QvqWsPxPbafrE9J5JmYD57YJeQumv9MzpdGeiJ
Vn5P2nLmqn7MtgKy/L6mqnqntDcXTfEPxv5dB6HLYPdtWVUivu7Jmg2GVaxVKz3sUVEStOI1
wvmSoP560D6eRcPOzoo/YKUYhyMgWCJeQumuR90/J6OhRFSs+f5Q5w66V9OqZsZrGZbZaELd
urBUax2U7KbJ8aE3pftBOnuo3u7A7u4ArLDswoHdy+8soZKUgdybsmuUuqBWmAO8u+JZqoAF
2QO7d3dJkhbUxniAlzC8a/kzOg0Z6JFbhoYorIifVZ0JrS3pElFYP1WuG+/nwpHUcy9EpsVy
RVV9llgYkLWb7qypaDS8azOZ709WBdN2usa7Nl8y1l+P2sfjvSm9aIv5Xaet2NvRFy1pA/zz
J+1hNNk/WOvi94nWjRTtA1zRKH8rpjwXDaXanav6ncspeAVbM2hy0OtN8n6v1J6fRfjgbt5s
RMWcFO2ZHNi9R3/1wxyUsxvYvZX2lvyNhKWeBnbr9xfjuGg5e2B3f75SwNTdwK4gdnRD7E4j
Bnoij+9fXbUYtKhccgN9w2SyEvMHXncVzedkNDG6250CaW+9CtiquWh0t122Dn7NRyNO6opm
CQMTeBB5STn2rvJ/GjE8iiZqkb1XFaEsAieIVoy8347uzkUTo7vqP8dauYlVwqpbq0Z3L8P5
mg8nmzpD9SdNMoGDUXnSkOXN7H6E4F50RaCzu4HdXZVltDY2sLsrswz2Yx3QrbvbOHEHd3dg
99KnmozAuvbAbv18xV9tiqopH9glebtrvQw6TRjoiTZ+TbmK9pCnExNYTXlOkuG/0zu+OXSn
ovHXUHf20Ft2CkGoD7YvWkLvbnqgJqOpubOEWkYXBV0YeEkVgLPdzFKcLgyPoqHUnQVV/4v9
t4D689CatF2Wq97Bz8lo/Cdd/BIR88i5lK4wvVtikfHnj9rjcLr2bFJEpTYFZQl81Vtx76/T
u+2Ke2gbciB3J+0MVSl4Qben7ETAXrsDuzdlFyohYD/SwO7ldCXIBvZqGdjtKUWzB2qAtqYW
e6OTcbow0BNtfP9oTaIHvL5klEES7YtWdNu1m5N2KhqnZ9aYmoUWLOMOGSuiaZflvq/5aJzP
VVJhaYQaUS9JQN6n7E4XhkfR0EtyMkzpam4GKhvsSNlNRRPZqt6NKPvNpBLYN7IjZTcdjgg7
2Q6HazLUxe2dslvB6X5Tyk4yKCDwgu5O2FlFu8UO7O6EXRGQngzs1t3tOcVIJNY7f2B30ztF
9fYGdm/KriRuYMV4YJfQu5tEyunDQE/E8WuKamwkhtS0MlaJqUusRsN39vrQnYomTLZ6tuBE
RayjSa4VPe5O7276nyaj0ZefLXFuKmA3F09ajf4hK3QjtHPaMDzdG3byoNSzlgq2qUZR+rvp
3VQ0L3pHnUlKVhJQ6XqDmPJcOCGmrKpUoqPTwJmqv6uY8j7u9n/+9V//+n//+q///Z//4b+n
nP/jf/6v//ufW48p7NaxW4cYZEV/+qn+PwAAAP//7F0Ljuw2krwRwfzxc4EGtvv+99nMEvUW
mIHkEM1m99o1Y3sMTBCvsqgSg/mJ2MK+f0h6sCioTDOwe9l39JiB+ziw+9k3WFAd2N37y4Qa
EB7Yrd+fxXA3mJwe2L37K5ZyBr/AE7zgdUJ2w4pOwwx6ZjHRu4lzVcrshBjtiMxLJl34qgHg
czIa/6lbKKg5/eZSwIZuX7SmI/Iqmq/JaJr/8Eq1UlWsVzAaX7SC4l1XZf88aR/Posn+pDkD
d+rtV6PWQcu9vEa/+3pG7HMyHEqkUZSwquZ3JFShZkm7qlxqQ35NRsOpUpdMfm3lCt/05kpG
P02/f1dy9Wf1B6lXWH8wsHtZnkXbMfYsvqB7OUBNuaB2dQd2N8erDfslH9C9DK8l6eCRNrB7
d5d7EjAdObBL8qvXsnB8mmbwQ9OMKM/mbLmQgRMvvmhFtviO381FE66AuWUq2l/t+yi/WxFN
u/S5/ZqMpiarTlL9HzXUf0FdibSiUeiW3/HpmvEomhe/i+ZbrVydfcDDv9/N7+bCCT8PYS3U
ndhn+14TkP/Mr7Zrrcu5aDgeNYkqmmWrjLrNzD1qb4L3CyQI/fkApdYO7G5mVzI67nJgd+fv
qoLNcwO7l7mrEzZUOfzAbv3+Sk/ZUHOOA7t3f5VTE1Af7gQv4XfXGnF8WlTwM1MHflnLRwld
YPdnX7SE312LEc5Foyn0Gp1La5bgeKB+34reEOd310mVuWhasjBBEdXeegbZalvSpn5Tcf7z
pH08iyb7aySHcHW33gxtbshLOnFv6OrndDg9ygalZpUQ3oHp6pJwLt8DX5PhcMriP5qmqgYr
ReapJ+1N736LHKH/uFCl94Hdy/JKauAZe0B35++UQQ41sHs5noUyL5ghO7B7OZ4kPwxA+bUD
u7lGW6IxASTxA7yiRtuuNeL4NKrgJ/YBkqgbU7HCvSt48MoSGzJ6sfirg3cymuLXzd7JJAc9
AqNZsjctX5sSz0VTU3PuYBwmcaygV2ws+m6OdxpVPIom2FrN3V91reRm4NsxL/GrYbEbjjcZ
TuvUnRURaam1wEMjS7QiL4fOvybDCc1ZsjAnbx4MWLiLRW+W93dZ3n49QkKFpgd2L7NjZ5Ng
d/sLuvfktwQ6j76QW3eWe4xSg6T4wO7d2Z4aqvQzsLvrxgaPhR/YJXm7G053OlXwM/+A5q9w
6hr3CgNpvi9aY/t7w+lmo2ndSV0OtTvY2mHFMeuU7iaVMhWMpJpbDsvf1nF+WpdYj12OaP95
zj6eBZOjscuI2VSUDdSjyJOtXf9Zlb3xl54Oh5W1dCXnQAorTC8J53rk/GsynJgep+Kczl8C
XDLojTDZz/BmdL9ChzB3cPZsYHcXZgnsejqgu8uyYqAN+8Bu3V3JkeYCJUoO7Nbvz/9MQw06
BnYvuSupGzz14dAl6brrkQo+DSr4mW1A8y8u8lvGuaA3kSUpIdLLzqHP+WhKFZMeyigGlmSD
3S7hdtdzpnPRSNLGxpZz7dpAxXpZMm7u5O5azpxPg4pH0QS5s1ylUS3mBALV7ft+cjcbTjDU
Li8n44Jz1TUF85t7xFQ45AeQUOsUlVlC3RF80Zvc/W1yt1+FMIO9NwO7O13XMyhSOrDbE3bN
wErdgd2dtNPcwHbFA7s9aZdB1v6C7k7ZFXRWdmBXpOz0htedBhX8zNKhFcnq5xP5Ox2mdWu8
Q24ydrPBtEaFcmGOUt+vSdlNRSMvzXSnDUYVtdFZlbG7mnH585h9PIslLOGbE9Tu/xPmYzAL
+t4E5Od8ODE647EQaWfQTHFHxm4qnPB1odZy/G6Mwbt+LHqTur9P6n5KhpDAKdSB3Z2x0w5y
p4HdnbMz1DpsYHfn7AgV8B/Y3Tk7IVTH+cBuz9k1cH8HdknW7iaXcvpT8DNHh1diSJm5K6PK
maktyD1E+9j1qTsbjXDrJbOZVFTxak00ja6t4eaiCQWnF++OWiYXjKzGou/O2p32FI+iCUYk
JtqCeRPYa7GI38mlPvvn34imGLP/IrNyzvBYyBp+d3OTmAqHkoQGYa+9lNAR+lcn7QTmd0/6
xrEHvqwohyyb79gvvyco5zywezmnJv+tw251gf2BOjHMOQO7O1/ciOF8cWC3fn+Fkxl4MA3s
3v3NkpjRBugBXsE67drdhE8HDX7moGFWggWQH82KDkulJZVv45ta8VQ0Ehya2JwPVCawki+r
WOdNqmcqmhKX+WaUu/+ngHp1sWgJsbkRAjoNNB5FEx5vrBb9DtyLgh2nec2kyiuBcv+oPQyH
kpNnNcvCpWW4yWLFQcTEN20JU9Fw8hBay2b+pFlDdePnUhG/nXX+m/T3BG3HGti9NK+k1lFX
pwO7m+b1gvZVHNjd+5sr2K44sHtTd5qogsZQA7t3f6UlraAJywleUTq+O3xPJw1+5j0RPfhi
rXeVDPZp8RK72Jh8vD57p6KJeWRuVBo5ZcUnJNYYE9O1s9hcNC1RIW3+d3RpgRO8bY3Q260K
32mk8Sia0NMLAb5WnX9Tg1Valqjw5cus/OdkOORvxUImTTs7D0dHXlfUaPyD3gg+TkUTLq/Z
fzCUM2tHVVrqPzK3+K8Q4RMGj9eB3V059l8UXDkO7G561xRMIgzsXnqnyVCPgYHd+v3VUJsH
O1QGdnPXZ05k6Dt9gJd0Bt4cuqdRAz+znfDfbq9ZSYp0QgnRiufBv5ebNvypaDRxaHE4CyZq
DO6PLrGdcHp3bWI3F01L3a8GzQmEkFRQ0SQWLcni3Yzznj4Nj6LJqVZrfhFrxTdJFZ5//XYR
vqlwnKkRVVLnd1lQRhSLlkRz06YwFU2YBRoXbk26bxHYkD1pCfLmd79Iha8/UOHru1X4auIK
0qiB3UsDalIDG/AGdi/Nc+qbCcySHdi9xdqcrIL9agO7neYJo2naAV7SInit2SKnX4M8c5/w
E126lhZiYmBifJkO31U0n9PRaKXcrbXcO+FeGksGe+lqauJrMpqWitMIsxpUr4DWgbHom2me
nHYNj6IJwtaLWI/RUa0NHppYksW7TH9/TofTLK6/VKUUUfCXk5fMTt3yvLlwwklaVKLtqveC
ZlAmVcrfPO9ndfgUVI08oHuZnSQRtA3vwG4++VOpYJvbwG7dXS5JKjhaMbBbvz/h8NzDzuUX
dOun05IK6h44sEuSdzdn7enSIE+U8ymVJtlKDPSZgtr5sWgFq5Pr5N1cNJyyqWZ+zSdmsJoZ
i5awuuuC2Ww00YhvjbUJLpu5yKPh0u/tz5P28SyanJyYUuE//wBp0IpW+BuS+jkdTtyCPJCw
we0Kpr0X5SL5RhpoLhxKMULu8TCJwm1Fid7qygtY3Q9N9hKqsfyC7m6+85sf3HwX2N3VWcng
PXtgt+6u5KTojMXA7iV3r3ommEM6sHubA3vqHfz+BnYJvbtWbZHToEGeiea3YlIqWYv0Ayx0
ssQg7VJ+4nM+Gu2tkIRAMWoZ64uW0Lsb2Za5aMTvfD1Uo6uRUIOtQNbQu6uRhD9P2sezaGKm
ldS0xFVCGjh/tmgSli4353M+HD/zrJZcG7WO/XA26LbMRROiyUJO60RKh91830LLC8jdfi2+
AvaMD+zupJ3fLsCk04HdnbSr6FDAwO5O2jETnLQL7O6kHWdwkHNgd6ftKoNDKQO7hNddq2jI
6dIgz6Tz/ZgVdipkVRXtH/BFS3jdTS5lKhr2CxypNq01SmWgVKcvWhBNvaz3fU1H0wtT9Vha
hIRm7dZU+65nd+T0aHgUTGTtnAI5ccg1F2moHt+KYtB91m4ynPDNUCtG/l1lOGm34D50n7Sb
iiaSdppjrrnFPDuqc/Quxa7gdT+UtFMCa54Duz1th44sDuzutF30L6Fpu8DuTttJAd+xA7s7
bdcMfP4Gdnc3oB+8cDdgYJf02t2k7U6jBnlqoqEhHJRjDg+dAlpjomFyPcY4HU0VpV6pd6OO
qootMtG4SdtNRSOphExn6xbJrgqn7RYkIW/yXH+etI9n0bwE7Jxnae+1oh5ci/Jc8tdP2vNo
uKqEuYn43RfMEC/z0LhJ202FE8rJrVkpJYeZDtqc8c/M232LHB8xeHXmFXmAZaMe2wX5rIEz
AAO7vRMQFVke2P3FYuycOKB7OaemoiBnH9i9nK4nLuAg78Bu/3wC/joGdgXn7DdM4HSRkCfa
/tGirc0Pmt5EGizGtyLBfDvGOxeNJtZaQ5e3+r80jNf4ohWl4tpvEj3T0ZhfprRQ5g6ytDXR
MF2mrf48aR/Posmp9NY8jmwtqyk837FglOiGpX1OhkNJes1+Fyfr3EBjeGdp3xvN19+Ipgj5
j6fULrAn71Qwv51y/qu0+Bi1MTiwexmeplbRsueB3c3wegbL2gO7vS2ggXW1gd3LoUpqrYAc
78Du3d9MfmaBL8MDu4Lj2Q3HO60k5Im+Pyc1P6tCI621yqgG1xJLOpOrqdfPyWgkTJD96zZl
kwZ60smSSmtYzl4fvFPRlJRJixU/eSsJ6hOwRg3kTnBZTieJR9Hk1JyuRoGilMYG/nbyEjVs
zpc/nM/JcJwVcWjwkf+ndvAk8kUroqEbm4+5aDhlzi8NHYrrEXrVmxPgfZO83yDFZ6DS8sDu
Zne1oUrLB3Y3u2ugr+YB3Zu/6ymjFngDu/XbqzUx2rMwsFs/XytJGfx1DOySlsArNuQn7mnY
IM9U9IW5VKLMBZ2ujDULgtF+7as1F4z6HaSyZa3GzcDhSl+0QmT5JRd1dd5ORWOJRLn2rtyL
gVPjNjlc+Z/s4dKP7s+D9vEsmpzMrPqzZiU3jwsVWV6hrHUrsjwXDvkrsZqWkP4StDeYEi1J
3112jnxNR8PclJuH4kEpSlT5Pce7itr9kApfF5BBDezuvsCQmED7AgO7l+HV5KQX/LEc2N0V
+I56aQzs3vyd+jMFco6B3bu/HAI7qJfGAK9geXd5ldOvQZ6J6DczUWm9F9aMKpys6GMlu7FP
nYtGUg35vexHVa4F1JqSJWaw1C5dub4mo6mJmodhTZ3kdTC7GouW0LxrWW857RoeRRP11nBM
czJRnXWBXbXLqrQ3yeLJcLo/wP6b4SaWBbzw+aol88l3ZdqpcCjVSlWpkN8rCFWimBxkefO8
n1XhkwzakQ7sXm7Hfu0GyxUDu/fstxBHxXX4aK59dn6k10/nDHK7gd36/Yn4d4KO9B7YvZ9P
cYXvgV2Sv7vRRzutGuSZG4CWbFScEZF2+I2+pDarl92En5PRhGQUFz+hWucMJ/d90ZIE3k1W
ZTaabmRWerilZTSaFdrXzuxuNB9Pp4ZH0UQCLyQSs/MgEYNnem1FO+HtTO9kOM0JUOnNmv9y
GqgqFau+tXL+NR8OxwXeWV32axH4sM1Wzt/U7hdI8VHqaIfyC7q7OssMKkwM7O7qLBuqBXZg
9/K7qBmC5bgXdDt7gqvHB3br5wvtZFyvpSyRa7nLpejpz6BPNPMpFTarTiGaszuD5VoWFACd
hl1XzOaicTaU/RbnpxRJEzAaX7Qia3cn1zIbTStO7krO/pdUtCdyxXQy06Xh258n7eNZNNmf
tB5Vc2nVGRHMHr5dr2U2nEalM3XNrbYMi0avMOsMJeS/etYehkMpXi6lizSjjM6eTv5y3tTu
Z4X4CtgZcUB35+yqoTJ8B3Z7zi6DSYOB3Z2zq7A89YHdn7MD+4wGdjfrFMFZZ2C/OWenp0OD
PlPND4nYEo3hwvX35OzmonnJvPsSbTkUidEWwjU5uxtPtNloOGcmrqHi1Auqw7ckZ5frddOd
nv4Mj6LJybQ4Z5CoX3aGBYm/PWc3G05Uyv0XE7JAcGfGhpzddDisPXfJGnli2LFujqa+id2v
UOJj1P7pBd2dswM/3Au5O1+nBJ79A7uX29Uk2mHH4MDu5nbNQHn9gd2bsevJDyiwX+HALuF2
14YGetoz6DPN/FKimC0i2So4guCL1lhnXEXzORkNp+yXzC4SxeUMVhti0Qpu12/O26loJOXc
YppCsv8T7IKURbOy5XpyR093hkfRhMdZab1HUtVKBfVJ8xpJwVtuNxlOy07uqLCp3yLAsf5Y
tSKcdhXO12Q4lKg09lueWi4C9qj6on9kpx1/hwgfOFu5YlTtEU8BKcqCN+QCGvxDwoAlg1Rk
YPfSYHH6CErHDex2KmxoNfDAbt3fLkkaeDcf2K3fn5XUO5jGHti9+6uawPMikEto8PXAiZ5u
FvrEYyBmYYxMs9NGbqAgmC0yCObrKYC5aMJSSIrFpVLEQINgWZOwbXRDg6eiaak6b1Qnj426
gTS4rXGzyPVanEhPN4tH0VBqjUtlqmExAw/irpDAZ76Rop6NJi5afnUUUWuwsfaKZLrf8/7y
SXsYDSe/neSsIXwONyf7onfhehWx+yFZQPR3eED3sjvzKyOYaBrYvad/Tf6SBF9jB3Yvu9NU
wBaUA7qX2zV8Yndg9+6utJQ7ekkc4BUM70aOV09DC33iMmAp/Cyqn1VaszHGImLRdzO8qWic
rInVHrORLTd0Lijpimja5ajG12Q0/tg0M3POyvxqfYQIXl4gg3NP8E47i0fBBFcTph7Ghbkw
mlFfQvCu84Kf09FQqfGgGfdsOMFbYiXXrtUn56KJJqXGOfvmKHVw3DQ6w94Ebw3B2y4JSOjQ
7sDu5nYFLLkd0N15O38ZwzZygd26u5TF35qgrucJ3voNlh7XY4zdDezmBtSWlMDS1QlewCBe
jRFXh+5pHaFP9PxL4lyKNsvSC6qh7otWDGu8yOTVoTsVjSYSClXhLr1Vwg5dXaKkRy8LpKtD
dyqanrRopag7+L907H3Xl2QjOV+2GPx50j6eRUNJa4j5FMsh+wy+fdKKrAFTvnb1mIsmpxif
8T23Ek19HR2S7iu4N13ObH1NhsMx+FhL2MhkU9hie24a8c3vfosuICW/2WObPbB7aV5JLaO9
dgd2dwpPGU/hBXYz0dN0XG0honeA9xI9SaD2zgu5meRxUnTO4QQvKdLeZFZO7wh9Iuhvqdee
Ww6/YKaCFmn7miLtTa/iVDSSirSWtUpxkgfaEvmiNSm8m9LZVDQtVbVecs1hS4QKjU9mVv5r
vvimV/G0jngUTQwvFfHXSBcraJtvMMMVZU27IXlT0eTUekxKc+mFYWGfWLWEs17LFM2Fw35R
1latSpPaFW3ynRPsepO8nxUFVNQjaGD3EjtOfhfEB4z79vxOqrCnx4Hdu79+nKHF2YHdu789
tSJgleDA7qWdnHIGb7kDuyJ7pze12dM5Qp+ZekTjee7N/PAzwpoJeUmHF1m+IXZT0VAct37s
aXEO3EGhNlpy2lK9HMn9moxGUudWzF8NmeGJJ1+0xuHsL5+0j6d7k01q9KuFbRtYN49FS5jQ
Xz5pD6PJqcYQtlom56n4uPSKBuGb1OrX9OZo922REMGhYqgrr71deRcQu5+SBOzo+X9gd9dn
icHPN7C7K7SCFrsGdu/+ahIFP9/Abv3+JKdSCRSQObB7+V1O1MDJmYFdkri7OXVPywh9ZudR
c9MWYhhhx4n2VS8xwLC7nvepaJyqVTGm2lXQvB0tUdKLXr/rM3cqGL9V1SJMTSRmRlB6t+Ii
cU/vTr+Ih1sTPWpHrqsIKFBCS+a//bm+afKcisaJmmTNhYo2Dwd8EcSqJfTu2sxjdnOc27Ff
847RJDSn+hZ8/vvsbrsqoBi2vwd0d9Kuo06tA7s9aVcErMYe2O1JOwWPvYHdnrQDxSUO6PaU
XQN7FQb2u1N2p1eEPvOKqKX51uauvVa0BvP9GbupYCL5Zq3EWGbNhjYapL5AyuM+YzcVTSTf
WhEybSwZbOD1RQty1/eU7jSKeLg3Tul8Z5oTEqeqWyndbcZuKprIvTk17VaaREskTOm+PWM3
uTmRepTKOQZ33vm6jYzup+QAUSOdgd2dr7OMChYf2N35OlNQyWNgd+frlMF30sDuztcZgz3K
A7v181lP3FCllgO7Il93aQT2P/5/DQZhz8winNuZ5VayH1RglYwXqaFcytZ+Tkbj7O5VIcsm
Vir4+PiiFYLPja740NdkNJKcoHZS4d6pgCOMseib2Z2dVhEP9yYbUQtPQJECT1N8ez12LpoX
u1Nt4m9Gzoon7Nawu+uE3ezmaOZuRqwkHb4W6T+S38l3aAKCD/ySnt9lMx771fdQZ82B3cs5
NfkvHeScB3Z7jbiBxnYDu3V/K/ufiQ7vHNjdCTtr2MziAd27u7kn7SBlP8FLOOe1eZydRhb2
xFzArxPUc5HqlKk10MhClwzTkPG1ychcNJIa5xqE00g7OKMuSwy9oi59TQSmoilxHyDTwjkr
egEra4rERNd2NnbaWDyKJuxsSmdnNp2to9Pva+aRiW4452Q0ryCsURVmWKBlRVErbGf+6kl7
GE0400jNVDplzeAY0aydzW+nnP8mBT6/zoJ5kwO7l+OV1NCX+MDu5ngd9Y8d2K3729kvhQVU
WD6we/N2mqiCcxQDu3d/taX8mnKERJYP8AqWdzNYaaelhT2xGbCkWrpUatVaA2emfdGKXJyW
m8ziVDSSqIuGkX0Ja10wMe2LlmQWb87eqWhaqqyFWhYuTiVQGb41yat6rehtp6HFo2goNSlZ
zPxa0cnQ4mRbUgVv1z2ns9HkWjTaAEO9TtBoVtzlWS4tGL8mo+EUTsfFRNmagm8BnuxQeLO8
XyDDxwoaaAzs7rJx9/sgWjYO7G56hyZEDujW3aXM4eyMyvAd4K3fX/XrLoMp2oHdvL/hKgL3
BRzgFV2BdnPonlYN9kRAv/iJo1wpO42QAkZUlhxTZJdCE5+T0ag/CmGJ5RRPO0q/Y9EKesfX
bYFz0URtpNQeEtiFGXwd+6IlIiB3F4nTquFRNJGPy12lUM3+ZcHTBGtEBa8FH2ejySS9OO/u
dKj8YfRuidPfHb2bioaTsPVqIWUT48kgvZP3pMcqevcjKnzZL09gEm9g97K8mriCjrwDu5cF
hLIe2Lw4sNt5HqreOrB7C7VhA48Py9oSm7lHcz09NUJbnAZ4San2WmzZTrsGe2al0RpJzdU5
V7hPgEm8Fc3AZHzVgvY5GY0krf7f4jxPckZdOpdovTlxuenZmoqmJydEIaVDqpLBKcu+xq/h
tlR7+jU8ioYiXRwCfE4gW4NnrVeki6MO+VdP2sNoctiUVyd6/uqRhostr+hEvRVbngsnGvyt
cvG7RBWQgb+1lv9/yvAJbIB7YPcyO0liYPVlYDef/AksLtIaS9EHeyuW/I0E9icd2K3fnXA8
T+DnO7BbP5/2lEFBkwO6hNFdvcr9nD0tGuyhbn6tRbPkQswKv8vXDHzc5O0mo3lJRHfrrywk
Kie4YmTUGd21OdpcNJKI6/8Fg5r5rjADueFAf560j2fROJspWkS7OE/1qwlGt2PVknCu7dFm
w6ktEnbV/EIUsnXoxMf3ur19TYZDiVqllil2Hh3GmWtneDO636G/x6AUysDu7rvLBEqhDOzu
wiyjfYEDu3d/JVX08w3sXnKXE+o+dkD3JhRjahLsqhzYJeTuZpr3tGawZ3r5pdXSi/jJ2xpo
m8FLCn9O7q7NDOaiicFcEsqt9kaksL3qig7C2m+KslPRSOrOVLUVp0IdHRiVJcoz99O8pzPD
w73x65c/ZD16IjvoeBSLVuS38g23m4rGWRp1K0rao8gM+hKvmua9HEn6mt4co1Aw7dlqFziX
OlcFe7O7n9XfK4wqtB3Y3fk6NdRW4cBuz9cZ+gM5sLtzdh1Wfjiwu3N2hOpsDOz2nB0q6z2w
S4jdTQ/Uac1gz2wzuDcm5tyJCkgeIkf63Vm7yWiyFb/BqX/duWXQFntD1m4qmkjAsXAwCDos
vX5J1u50ZngUzStrR736DnExBTdnR9ZuMpxaI/+YnRB5TKCFWF4iX3mftZsKh/wVWpt2lSyS
QUP5SPW9md3fZ3Y/pMMnGdTMGNjteTu0FXBgd+ftFO2AHti9+6v+4wS/v4HdnbdrFSRQA7s3
c+ffiYF57YFdQvBu2p9OcwZ75ptRelautXKvuJ35oszdjSbKVDThgdFLaZLZf1HgoUtr2gZv
M3dT0UQSzloLDdHGpWK6G75oScv+Xebu9GZ4uDdZX5PZSmKvYdx9mbs744y5aCIH1yu1VnrL
BTUUXGWccZe5m9wco2hOFb/plQYOZv9TM3ffosNH4GFGSzIBy+Y8tivxVbBad0C3NwGCzdsH
dDfjFAGVswd2694WSmjzygHdy+d61M6xT/eCbv10VVIGt/aAruCadNMCeLpG2DPXCN/VGL2P
vzpo3yNLGpnuR3enotHEGrOHIlaCQKOjuysGbtpdp/1kNFqFaxMhAesmumRA5Uav7s9z9vEs
FoqdCRHB7tdW1EeIluwM57uk9WQ00ll6Ub9DsoDuyLFoyd7c6DxORuOXTGea/kWJbw9KNOee
tN9ONP9N6nuKzr0N7F5mp6l1dLzjwO7mdq2ihm0Hduv+Vg6ZMlRgmVY4tz/hdiV1RbvsDuze
3c0tSQEN5U7wkmzi9clbTueI8kTO3+lNbZpr15K1oJLqq4Y8rsd256KR1Iv/kqJgTIb6gvmi
FWO7r6vSxck7F00UGZh7L9Ybo7fsskT9+sY44s+T9vEsmnBtZcm9mdNVhl095qxe/ys3ep23
no1GuFELH4wsGfaPmZMz+a+uxuu89Vw0/ob361ZYrWujCvbPxqI3x1vD8bZr70kFdbQHdje5
87cpTO4Cu53cGXr6H9i9iTtLWcDPN7B7k2M1+UkAau8d2K2fr8fYC/hOH9gl5O66Q6ucFg3l
oeGE1db8lHKqVcC0iixp0CLT67TKXDSarFEO04lChA4S6BKTM2p8nVaZi8aShbCb70sJ1Wss
zR6LlpC7667Tclo0PIomp87Kor2qlpASBIurK3pUbpWV58KhlD2SaFF5CRLDQ69LJnAueyy+
pqMR4a61eigGtzi9pffWsbsfk94DSdTA7u4HNANL7AO7l+TV5Jc78MdyYLfub4vvBOz3HNjd
/XYdtoU6sHv3VyQxg1/gCV5Spb3uCCynR0N5opzvX576fZ+Ea1YFXQ10Ujn/v3J417K3c9E4
n861ZHWux5Y7OiRRF3QfHJrBV2fvVDQ1lbB865V8ixisnvmiJR2B7XpqvJweDY+iCR30MOZV
1pwF3BtaIn59Q1o/J6Nx+knFornBqkcEalauIq31huZNbk6oIUo0nrLA3ZpznSdvlvfD0nuo
s9fA7mV2nPxnBbbdHdi9J78lv3rjo7yO3bq/kpOh6aeB3fr9ORcqho4aH9i9n8/3DLzlHtAl
ybur17mftac1Q3km/9+tmLXeyYkn2Hvni1ZEo5fy/5+T0USxiP2KVPwaZ2bfW2H6z8psvjlq
J6Ph2plUsrP5Ao8lr7jBMl16vP150j6eRRMzDr2asyDpUhkUA/JVa9rvrgd5Z8NpJKWXEvJG
vj9oOCv6l2/GrL/mwylRk6X2uuIx1tQwO2b9Jna/QIGPU1aw925gd5dnGdUKGtjd5VlGHWYG
di+/iz8T9RQ4sHv5k+8ZXC08sFs/n/b0Eq7HZo4cuoTfXU9XltOUoTxUyucuvTk96USgR7sv
WhHNS93i6tCdjIay1eyBZKd3sJ4grcja1X5z5k5FIylTpyJFnBQZaLPoi9bkuW743enJ8Cia
4AJcS+YcVhPSv5dBPOF3s+GQtp79t6MeDu3ldzdCLXPhUKLSnHhroV4Y7MmmSXOWN737WQk+
BaXaD+jurF00oqBZu8DuztpZAxvUB3Z31q6inhQv6PacXQGN7gZ2e86ugGImA7uC1ZWbCtlp
zFCeieX3yKBEv52WDCqA0JoJBMs3fVBT0ThBKzlrZRY/o+Ck3YoUpLPi64N2MhhuTasRRRoF
1P8IOcUVtOGvH7SPZ9HEK4TC0Y1KqVHx+zVJu8lwYtC8MWdyAgxWL3fk7Gaj8R9/TDNXf+SK
vHN2O0ndD+XsSAqcswvs7pxdBWtIB3R3xs5vQPBARWD3cruaioGfb2B3szt/04Cf78Bu/XwW
DAfrcF/Ehe6ElcvpylCeOWZwiGb7TyNzEdQzepGwst6ct5PRZOf4VWvJraFFJV+0xuD2Jocy
FY2klxlDN78XlEzooMsSg9vbYYrTlOFRNM4D/AVHoR8Smk8os2tLiOods5uNJmtm6516ZlWY
Cy0ZprhsgfyaDIcSi+8KcRXKHdRXp8m0/W9ndvz/XnfvEUkB+cmCV+QCHvxDaoDWDJYDDOxe
FhzGIaAg08Du5sGKWiy+oFt3l7UmYQK/vgHeyzNragry4IHdu79i/lCB18QTvCTPeaPmcVpZ
lEf2Apayv4CFRalVMKBYs4IN841uzFQ0kiwq1z3GZwx1+YlFK9hwvhktnoqmJeaYxmVyqqJg
Z0FbM6VBdNMHexpZPIpGU2+1Bq/v/jc4QeOLlrDhy2rv52Q0Ue0tzuyJqZB1tKt3yU3l1fN+
/6Q9jIZTWKYUf41Wpg7fiecktX87Gf43aQNKBiuxA7uX5VnqhPYnHti9LKAm/yPBM/PAbud5
DA/wDPDWb7CEKBH4AQd26+frnKyCE0YDu4TlXZ1WfvaefhblkcmAOgPVXDo7VWZwzuG1aEnS
86acPRWOMzbuUk1I2dk1TPNWtFw2vjl8p6Lx2wFxDocvloKKc8eiJTTvph329LN4FI0zNmfg
hf2noNLRNqlVAjI3NG8qGkqcM5loWONlsNcgFq2Ipt6UsyejaZrFr0hijFpKxpo3y1vD8var
A4K1zgO6m9xZA4dPB3Z3Cq/6lQjN4QV2L7kr7K8ZcH9P8NZvsPp7ENUtekG3p/BqeZDCC/AS
cndt7lFOA4nySNjfUmn6YnZmFTyiYs2SVsUbdcCpaF5zSLkQGzci0EguFq3gdnRT0J6KpiVy
jmXOVTUqjWgKj5ak8PimV/G0kHgUjaTKtVXq3KN3ApXlXuO8didQNBUNRebbpLfcOqGp7yWZ
b6d2N5eIyWC6ZDbqIlYN1rGe8wN4c7tfpA2YQQWZgd1L8kpqBNbxBnZ3Bs8vqXAGL7CbSZ4T
8wa6Qp3gvRm8gmvIDOzeHc5R/r8ycPlfAAAA///sXUuyJDeOPNHQCJIgiAuU2bx3irFezWK6
FzP3twEyImohWbA9WHh8pe5UyWRaOKVEMjLoxMf9j1t8gkNo3n03mVwuEvLIqaD5K16LUbxs
nxHUbGuLr/g/lWrvhWTWwqlplFIruS9GziiVGBEUXCaJlbVg2L7lUrjn3kULWLLgkK0xmnff
EyCXi8TDrenixseVhEcBx4xryIViqg64Fk1O2qjVoWo3JFZQKDSHyGpObdzWwnEbNyIqI7Pa
fx0VgV4Tx3oTve+VB2zou+TE7iV3JYmgTXgHdu/Rz8kt6dF8iGO37q+2VBW8d57Yrd9fzcmO
AHDU+MDubRIcqaCj0Cc2gti1+8YouRwk5JmDhAobbSisWSuYwLNFIfm7Njlul6KhpFTFZyZb
awo3RmlMC969QOBaNM5qXCfZmF3NuBFdD7GAvR2v+fmk/XgWjcsdug5lN/rQB9jXECR3WGbE
bimanKSoMbrM3I3eDdSrJCgdee8SuBaOneB+fSi5lUYVlFCgxTaAN7H7DeQBfUQSlQc8sLsr
tHmA16UTu7tCWwfaxXBg9/I7dzEFm9tO7F5+55LioCTaC7r107Wa3F8U+3Uc2JC03b2ph1zG
EfJEzd8uFrU1O2xJc89gPZNDDqk5u1uKxolaK6KtSha08y6I3Um9L5qtRVNSby7XRi4B3cC9
8UUh7O6+D0Au34iH0ZQ6upC78vZeYDHriGhKvx/lWYvGFW58NJeMf2dGGwltVUDLasm3KqGf
i+FQyrW0wj6KWAlWgc/v+uyvs7v96oCo6e2J3Z22s9MIdvVw7Pa0HYMlzxO7l9Zxqqg0xYnd
TesKehk+sXvTdppqA23jT2wIsbsjD3bcXt4R8kTPv6fclIcW5Zy1Ymk7WxQzUnHfDLUWjXG0
4Qa2jey07R1O2wUkumiUST12KZqaXErPLfqkCoOnrS0K0ZG59Vz5+aT9eBaNKxaJsQYjq4Lr
HUYIFpUXU5k/aA+DcYbWODe7jnvijvbyulnWbikc1/fNvRO59VxFbUZt0ZvX/Tqv+yaBwEqg
dsaJ3Z21awK2tJ3Y3Vm7NtCq7IHdTe+4g7/jE7uX3rk9AXi9OLF783bsF3fw+nNgQ+jdvdmC
XNYR8kTO/9UQUEd2MREVUMyHQ9TOjN7dkdWPxWhKytmt470FisGcua+JSNvdatZ8Lgfj7WlN
GhMoI1JiqN20InuZRjwMpbDtSGvViN1AO6VDpl2mEoFr0RhLG7m1PkSK/XBAFX1fFRHOuEuo
fi6GQykP13cZoxjzRmcBbdG/IrerXyERCKYBQjIAYZMe26X47JIEnqcHdi/fbMYxULuRA7u9
SoxKBZ7YrftL0pK39YMzKAd46zfYSxpon92J3bvDJMZU0JG3ExzCOSeJnsvZQh6ZjuTUWdm4
TbN/oCMetihi+JXzhA4shVOTBdJyMUqgrOD5WRf1Jv40yjspFi9FI4mMOlOprqPTCSOeEmKi
YsRzMk10OVs83BumSnb578q5D7SxMUIpsdDt3nwsRkPGiCVX1eojHvBQRIlR45vUipeiKXYK
DducStm/K/SKsybv8Lvzzn8rNT4G63Yndi/R60nBaYADupvmaQHTTid26+6W6uPD4E/5wO6t
yrbEAo7JntjNXQEvO3hUoPgAh5C8e4E0uTwu5JHxgF+CemPX4CIuYERtsRXoT5nFuzzpx2I4
NRU7Aon7GDoayMJriEixkbxJymcpmpHUrle2P1RfnVqgXktEf2PJeq/XIpfHxaNoWhJq2kv2
BscGDvL6oi9Nx30sRuOZtSpUymCyhw28HS2m4/5I8vLkOrEUTUmqbWSl0d3/GByjXGy4eJO8
30CMr6BpvBO7m9155h6ld47dze8G45Yajt3L77gn0ozqGR7grd+gkCeXYD0+x+7dYTFaqWBF
4AJHMDyZHLuXb4M89NQgFc5VendpMbSVNUI1dqrItxZOS4Wztmw0byjauemLQloDJxO9a5vj
V2cpzNwFrVv4mpg03kSq5TJueBRNTW7aQK2ruvgj2PVrP+6Q+vGkN3ApGiNrJXNnElKfgUUZ
Xox29CSNtxRN8eYluxex9wcPeLqovRleFMP7Jkk+RQ2ET+xeoifJTjyQpxzYzTQgNQb7K0/s
ZqI3ksvTgkTvAO+t11KqAuaVTuxmKs8Jvr4f2BCaNzl7L98GeWiqIUNaIXfgzQ021ZCImYmZ
d9paOF7c69LUngduFe0wTSGiOuM2ms/FaDRxds14NW4kAk7naFB9c0bzLuOGh3vTq2itI3PN
HbwG15hB5VwnKeOlaLL3iNgNrhcSu1WAj5qtiijXlplG0FI4JdnGsDa/HlFmuFz7ttX49RGQ
7Yp8FdSAOqB7mV21/yXqqHFgN5fw7C0GDha+oFv3ttvLv4EX6BO79dur3vUNlglO7N4CMnlK
EywgH9gQVjfpyL8cG+SZ/0Rrg6RqH92NKMBsV4xT2q3CycdiNMWuH9XCGMqtdEVnRyOURGnU
u0zk52I01a6jzUctu0slojPuMW1eVCbKQJdlw6NoKHV3OCnGUqUPwc4VipJZnjR7LkWTk4iq
/XCKtkxo6Txo9uO+o/BzeXNKtWdN3ZPP3gdgPmJRTOdN6n4DNb6SiMBXyondXqCtoOzIid1d
oK0Emgmf2K37q8UNeDF+cmL37q8mVXQA8MDuzSrWNCo6BXJgI/jdbb/af5ZxWTWMZ1YN3nun
2Uf6VEEPKw6pmNkjf++isRYN2RdtPFWkez4FzD2sWnr+cbD3tl/tczGa6m3DLNXIt1IF74o1
pvuObn19fz5pP55FYy+RYZeIxsP+oJO9FKEc/fqdzp+zh7EYT6NiP0b1c8+4N5a9z0GthJMm
gLVwKDFxdxbMnZui7G7tlfZmd9+rxtcL2ElwYncn7RqDtOTEbk/aNZB2ntjd5XbKYNrpxO5O
29WM9uUc2N1pO/DTvZAhKbt74dtxmTSMJ8r5zUU0+9DBRXJuaJt7hBfiNGW3Fo1n37j13l5j
wGD3oC0KSHJNU3Zr0VR7pDt3IbuQZtSNxxbFULr7lN24PBoeRePZt0as2kQKKUq3vzxltxaN
p+zs3sCZ7UbU0crWhpTd6ua4wHJvlexqx2Cp5J2y+0tL8RVQ5vyAbk/YNVD04MTuTtg1QUfl
D+zehJ3rsYIJxRO7l9mR7Rkss5w3m3t078wCnaFP7Fen6y6LhvHMPqOrnRWqmkVQVyQOMeAi
bvc9dmvRUBqjlVqVjERIQVWWIyST5um6pWhqGsxqN2Y7c7OAD5stihml+KdP2o9n0fgJYVFw
Lll5gLrEJWSQueR+Pyy7Fo3bnDF5RKO4TyycsItpGZxwu6VwKLlkdLfd6S9FPjRhtzRR9btz
uy+R4qMCfqkRboB/ZTE+2NvjwG5vAQTLJgd0e4m4gLm6E7t1d8m2jBkcTDiwezmdppbBGfIT
u/XzSbezHZRoObERnPM2Z2VM4HKPGE80/TWRfTTiXEeTAT4QGqL0Nh3fXYvGJ3GLsU0v3XXJ
4H05aHx34rewGo0YPSvN7lNaFY4mpg6pkxLx5R7xKJqaMmWSLr2pve6wnjlfFELS7vbmYzEa
co/y7Nlr7QPVqHfb25Aa8f0E0Wo03ISyjmzHeEY7m+xQ+FeknP9WKnwVzNqd2L0Mr6UhaJvY
gd3N8ZTQevGB3cvxpCV74eIqIw7ey/JcaBa84Z7YvTtMnGBt/wscUje+18Adl4/EeKTvn1NR
LaVzd6cPMBuXQ5y1iOskubgUTk1q51XTxkKCGov7opDk4l2p9XMxGrsfZPbWe1cCGeDkii2K
KRzfK3uPy0ri4d60nslYXu/U0G5AXxRC9CZdp0vRkNtt2w9Su/2dweFqXxSyN3dl8M/FaEoq
o7emQ3NtaEnHPfneRC+G6G3vGKtoR+CJ3c3wBLU1ekF387sh6NXuwG7O4fXU4dvaCd6bJZPU
FFSqPrFbP59qInB674CGcLtJp9bl1jCeaOiP1I00CJPklgtIp0dM3bjdkqGPxWhc7LDaX67M
Ao8kc0Qsctut+bkYC9tLoRfmzGVQzlh2lUNq4EYe7tW8x+XV8CiakvJorpjT7Sor4B2ixIgS
U727EX0sRkOJcjGeqm4jhQ4kU0j+bpYpXoylZR3kJtBsVwm016ItXSDetO73kd8TVIbixO7u
CuQODhyd2L38zhjHQAeiDuzW/S25pYYaVVzgvfk7thcP2nl3YPfucCN77EGdoAscwvEm1bPL
rGE8MgQg42t2pA8pygRqbr4WReTveFKoXQqnppfqTKmFRq+MFgMjOrZo0CSrshTNMF7ghc3e
dHAHh3JsUUj+btYScLk1PIqmGP98dW5ya00Ii8YWRUzz5hnNW4omJ3XPlt67kN2RQFsiXxWy
OZNp3sXNydmuRUbC2+CMmhgsulu/md73CvA11DLpxO5ldyX1gmoDH9i9Z78LWaDJsQO7t/ou
yU8MLCVwYLd+f9WOW0LlVw/s3s/XkwyQOLygIbxu0ol/WTSMh6YGw0hd5iEyGti6XqNyd5Ni
2VI0JZGdsEYdiO3IBfMQvigie3frG/u5HE1tyi2LUyHUotgNTUOI0ITWXRYNj6LxjrXKvXPn
YfcTuJAZQ+sm87xL0bxMD+0+6TujzLiucgTnrjxJ4K2GM6SyNup1jAw2NORF0v3mdb+BBh8l
HQUWa3Hs7tIsSD5fyN2F2dLB4YATu3Vvu6b+aqDGhhccu5c6tVQ7qG93Yrd+PnYnS4WlWhwb
Qe54krS7jBnGE7V8+2GIW86777ytxI5cWxQxddbGRKxlKRoXAi1SpBrTr7D9X0iWi8asE2op
mpqo2YPTB1Pu8D0nRTjwzMVaLl+GR9G4h+GwS0Sto3FD6389puVuwu2WgnGWNpgH9cZSFOxS
s1Ux3miT0fHFvSnkGo9dqnRUv4sWz9Q3tfteAb5aUdPIA7s7ZSegkNMB3Z6wy+CxcmL3JuxG
IlRE5sTuTtgpg+MyJ3bv5xOXJARZ54GNYHU0keC7nBnGM2cGO5SyHbNZsxZwLNMLnhGV2Nva
5cdiNMWnfkSE7cgtuARfRKsrjVvq8LkcTZVB3FVyrbZBaMouRrTu3gptXMYMj6Lxti6pzahQ
y1UqOK2/2Nb1p2gmMi1L0ThBswd4GMPy5LCgldgYWndbWP5cD0f9V/NqvdVXHyxWWH6XYgN4
3Tdp8FXUwe/E7k7ZyUArsgd2d9qugcflAd3bTVnTeL0lkG7KA7ub3tmrBqZ3jt2btHM3sQLW
sw9sSEX2nt7pZcygT/Ty7aPpKMOO2+6zmNhrvS3Kb/1pUPY+abcWzUtheWS3MmilgN5OGxSW
16JxseQjkNqHgipetiiml+ue3unlzPAoGkrSjN1l5kwiYO2fomTr7i8Sa9EYH8ruDl1KVguK
UBW+ETJSIfeSKKubU0bPQ7gIi4L5YfqLTsru427/84+//+P//vH3//7bf/zX//5t6/kEjsVt
ZkQgGwp4GwfQ7u+QIaxuLoyKCBzYvaTbjUrGA1OTiOG+Z6SbUSG9E7s3q+pGNKjW8YHdvb+l
gSMuJ3bva234XDx2PJ3YgJcJjfvhUr3MM/SZeYZ3V6oYc2ijgTobtigmqzqh3UvReObOLhFZ
CnOvsKVqROaOxq272+diNJyqqF2H3LnXHYnBMeaQrCrdEtWfT9qPp3vTG2sfo7rKIZxVjXBF
LLnfT1KtReMy1pTVM6suMAa+qYLEr8u4z6quhVPScF8oriN3QT1qfdFfkXb/XknVb1QiNOI2
0EnmE7uXBLBPhoLDVgd2L8mTRGC35gHdS/FKKqid84ndTfGkoq+aA7uX4tlRWsF20hMbQfFu
h37t4L08NPSZh0b2ZJfROx/WQEddcogb8W3H/sdiMHbVHL3ZqVstnAEn7yLGKWjc1mY/F6Np
SUd7WYKUllFdOF8UwvAmKfzLQePh3vQqw9u+XdocfTGmiG4sY3j/9El7GI1ztVZ5DHe9VoHr
5iEMr97qgH8uhlNSF3cVrG6WCDs4LPoKvhned0sQ1pZyRis1B3Y3tevoLMSJ3Z2/kwHOg53Y
veROXNganWLWiGmAZxJEAupxHNCtn06rS21gv40TG0Hsbs3R7Ly9jCr0mbWDVzGrESIpOcNq
Li2G2U0KmUvRkAsQinYSIRfbAdlDiAThmLSprUXD9sGaZ9G8mKmgtjSHRDOdc9HLqOLh3kiu
VJqrn0gD72y+6KtL5kvRuL1w72K3Im3G7kCxCldyC8nd3cuYr4VTknTyUry9AwqDqlu+6M3s
gpjdt+TuWhIBsxMndjcFGIw2Ph3Y3bm7RqDI34ndS/CG3abB3OeJ3bu/knoBC9wndi/Jy/ad
gJ/vxIaQvEm32mVSoc9sHXyC0baXmmZG3aBTjegkZL4fRliLxvja6K2SEVf1lsKdJE9uB80/
F6PhVLKxoZ6NFGkDtV180VeTvMuk4uHe9NGNQ/AwWlTB61uM1OWc5C1F43TNHrTcWAa3Dg44
BpG8dmux+LkYTkk9++hl79pyRQes+ltp+pc53mb9wTISbBDzgu499T2NjArUHNi9rI6N6YL2
BSd2L2s3pqECHuIHdjcrZkbbYw/s1s/X7DtB21NObABzKHJv1qWXQ4U+cw4wvuDUQd2ADPTi
sUUxqbu7ZNfHcjRERatPl/aGOrtQkERNneRTlqIpiYVtW1ywb4yC6g9G3B9KHpOi7OVR8XBv
sj1qo3Ojbn9QjZocQYPqrcndx2I02S+Smo1fETX7G53+7SG+cPRPH7XHm9PaaCJl+MQ5bIey
lsF/07rvlx80ytYZlB88sbvLsrmDZc8Tu7ssW+C0wYHd3VFp7ydQ1ezA7uZ3A/XleEG3frqq
Lw8E7Ns7sCE5u8mZexlT6CPXkKSkowi36jp3KB8KkVNkvneGW40m6/AMpAh3Qj2MQzy7jN1N
cnZL0RQ7clVGL3Y11QZ6w5WQovmc3V2+FI/3JqsoF6FeYZvcEHZX2r299Fo0zu6MpnZpXiYl
cDzNV4WkICc5u8XNqVpeztK1aAabnVZ7Vd/s7hsVCI2q+cQZSuscuzttN9BuwBO7PW3XG6xB
6NjdabvawGL2id2ftoNpXYjlyrOknV1uQQGnA/vVtO4yptBnVg5aWpdRXQOloA7VUbRuMiu7
GA1R5UI9c28V1OwLS9rdGbp8Lkbj+TdjDUZRa5cCan5HJe14MpV9+VI83BtPB9FQZZICSttS
iHyQ0bpJ0m4pmvxyoWKporkPsHoUxOqmObvFvWmNjHH3PDoPsAfbF71Z3a+zum/J2WnK6ID3
id2ds2ugv+IB3Z2xa7CO04HdnbFD2wAP6N5vz0v8AjKNA7s7Y6cVdXE4sCH12MmBe9lS6DOz
AJ/za3ZVp2oUDyyAh5ivzjN2i9FkrerGdpwHPMUUkhUyanfvvboWTUmt5FFUbXs6dXRyMaIz
Zk7tLluKp3sjVGsufbi2C1yP/XJqtxSNs7SsnFsZOSv6It2RsVvcHHtB5UG12wZVWKNm7Uj9
3bldhbndE+t67KyImAn/C0vvFbDKckD3ss2aHoh27NbsMAZZH9SH6+76MHsvO/j1ndjdu8sd
l1V07NbPp8U4LlghPrERqcSZ7N5lmKHPzEyoGZkhdx82qoYl32qMYy/zXfLtYzEaslvl6J3H
4OqWGV+aEnkyursUDXvbqFQh5wEMRsNB6arZVMfll/FwbywGLrVJHbmANaAg2T2a3WyWoslJ
mMvQQr0JCWE/nLw47PrHdsb8Tx+1h+GUpE1FO2e3zoG9HdfagH93vvnvJLunBTxkT+xeEtCT
FHBI4cTuJnkKy0sd2L0kz829wKTdid1N8hqq7X1i95I8u9U0sPnnxEaQvHvhvZpP2wz/lyck
L4to7TK6veJRw7oIjU0jl7dyaIvBuPCeO4Aw2VH1oilYaiTEsO5eWnkxGldJLqzuVSe5gQ27
YdLKt40JVzQ/nu5Nr4201CJaFC4XhwxF5H47I74YjXeA2KXIOGseY9jpgnK8iHAm0sqL4ZQ0
WIYXov27Ap2ubNFbniWI420X3oMnFE7sbnKXGzjheWJ3k7sB2xEf2L3kTtJAJ6BP7O79HRns
BTyxe8md4sYeJzakGXBC7uhiEM+MM1prXckInstugfn6mJwX820dbzEaTzUzG7uzYzcT2kqa
esSMh9x6CX4uRsNJs5RhZIgEnnm1RREGvpMM3hXNj6d708egXIwUDUVrL1+vy7IYjYvveWOj
cK5ZSWF2F0O9byvGi+EYUdPm0152N2JChTsWG0fe7O73Ed8baNPYC7qXAkgqil40Duxeiiep
ZdSc6cDupXjDTkOwvf/Ebqd4DOYXT+xuincMbmIUz7EhFO9Weq/mctGIZ8YZtUuWqlRZUSeV
MOm92+HKxWiM4rXafCjZpXwHmsCLuB6Q3JacPxejYeM36lLEXkVvqBJ6jCLxlOKVi0U8dM4Y
rmSjpbsFNiy9FzK9MqN4S9Fk19XSVycAN7tPwEXakB7HWQJvKRxja3bR09Y7ZWPhaP/peBdp
f33gY7v2Xnkgvle+RX2vgbm7A7uX2HEaHVS3ObF7abu9YzJqanxg935/I1FH5VkO7NbP1yhJ
BzXHT2wEsbut/tlxWy/y8MzOQCtLsWOAmr3WYfW9kNzdvRXpcjTUuPYs7s0gHW1aD+klHPWO
pn4uRmOvrVqNYomxulHBPugSVMu812e5ovnxdG/yGH0MuyJ2oY4SuxB9liyTHoClaHLqPvta
2VhqLgIKG+Ugh7d7KaDlzWnD6/9KeozGYF2rb0e0AF73TeJ7gra1vaDbC7MVJZ8HdndhtsLk
7sDu7qq0/yVI7g7sbnKnDGZlT+xecldSLmDl78QGEAg7SO6P3HYRiGc2BlrLYM2DsjDB4nsB
BMLI3eTIXYyGeNTqsv+dBRZ4i2jaoNEm1bKlaIpPDNXhxiKZq6LVMo5IDNHtoMjPJ+3H073J
qnaFYE9AZrCJMEYYsVS6HeJZjMZoGvsMfLffJI1MaGE24jVaiCZZu8XNaT33yrWqzyXDMi3v
trtfZ3f7xfcGKNlwYndn7exqDovvOXZ31k44g20lB3Z31g6cxH8h92fs0G7FA7s9YycE+mUc
2JBS7CSPwhdxeOiXUVorOWepvYHzslHSezNStxgNsSuA9DKKa8PuzNjJrXHv52I0xWXqyd2p
OOcKlmJLzITpRJ/liubH073JQk1bKbWTgPfxIH2WV4/B/El7GI3n3sgIEDejQSMLTOq+PGO3
uDlNeu9ETGPAs8zvjF0Ep/u2jB1O7Ry7PWfX8ElZx+7O2TUBqeeJ3Z2zQ+0RDujeb0/tyEWv
9Qd2d8auEGgRfGIjMnb34ns194tAPNPJH0NENdvVIndFX+sx4nt90v20GA0ZrxtUvTyfwW6N
oIyd3BrVfS5G4xm70jrZqjE62nuSIhon5uXYfvGHh3YZw/64gxi7ljdK7iL67Oq9mfJiNJ57
Y/Gavxa7FIGNI7YqJJ06y9gtbk7rkrv32bWMi++1t/ge/A2jlDnC/uGvLL+Henmc2L2cs7r/
Baze4djtdeKCenkc2K3767J6oLjIAd29u5VwbRbHbv18ajzygQBf+XIBvprl4jVPVPxdS2+4
MlCrpYug47shLI1nkhlL0dgpWEbpRtE8LQKnR1tEzXs627EUDafOWZm0aSkKztlxkGTd7TTE
zyftx9O9cW42spsC2S6htCYmPTpLXS9Fk5MYde5svxwVe9ZQMw+JCGciwLcYjmvpkWdIM1tI
cEPCW4AvjNt9kwCfXQJhAT7H7iUBksCm9BdyN70bHZyFPLF76V1JNEACdWL37m1LpaIO0Ad2
N8HrAn5/JzakDXAyvDsuEvFEyr+6771W6VmFOkzwQjwwJgrLi9E4VxNqQkVKzqAkWpDCsty2
aH4uRsOpaS/sXiH2L7D6HocM787U98bFIZ7tTW/ZWHBt3RhegwleTIl1kr5eisa1ku26ZRc3
zjQa+CaIUljWyV1iKRzjalRFmVVy0QaeqotSQG+C9xuo75GAavov6O5ysdEhuFzs2N3cThTX
3nPsXm4nacDCLAd29/42cP7ygO5ldupsDXv6TmxIL+BkwEMv9vDMO6M1UcpCeYwCnre2KMQ7
o99lID4Wo6HEwtpzluI9Z+gQQcSNlEQmx+1SNJy09lZ1SG65gMM3HDJZPZdl0Ys8PPTOsBvE
KFJLHl1RyZyvV95bisYFVhp5hlhtg9Bh5CBZlimzWwrHSVovxupKaxks6JTFjuA3sft9hPd0
ZLA4e2D3MoDh/r9ww2LeXpyV1NAh4xO7l+GN1CvIQE/s9swsaj1yYndzPBnYqXtAQxjefe6O
LncGemacUXtRrkVYGurA5YtCcnf3xdm1aJys9Ty0UW5dM9reyBGZSLl14PpcjIaTGEvNLKSu
r4wyvIjG5ynDo8uc4eHedLG9qZWaMMHaOV8uvLcWTfYrOWfKJXPnDmo8+qqAcGbCe2vhuIZe
YaeOuRlnhbWV38XZXx/32C68l2FhuwO7uyuLBjgie2L30jp2jUpceK9FDO0/G+HtA7yjndi9
399ITQUe43Xs1s/XyB0N0ClejRhGnMru0WXLQM+MDDw5pER5cC7gLGKY7N6tFelyNNSlyJDB
lRvDQ7wReyOTycq1aIpLu3ErRlFdBAQe4g0pYk7mPOhyZXi4N1ntatiUbXsGbEgcIrs3U2ZZ
i+alzDJ6z0aA7UYOnkNByiyzId7VzWlaJJPtjVIp8JzH2zIjgNZ90xRvL6jl2IHdXbYbFZyj
PLG7y7K14lO8jt3dTlkULMO9oLu5Hbi3L+ReXldSQ5VHT2xIs919jztdbgz0zL/AJSZG925F
Jdi/4MvlWVajsWCY1P3QGsF2qjGCyu0ums/FaEry3icjd0W0K2jcW0Ks3ebM7jJjeLg3xuyK
59W7/0GTqV/P7JaieTE7bWVoL9KowYLKX87sFjenDdsY90FrWRUVq3zrswQwu+2aexW1iTyx
uxN2hVHNvQO7O2EnAlp4ndjdCbtK4Jjnid2fsANvji/o9nQdgzMeJzakDjs5bC8vBnrok2EU
aPRcWCuDjZdhtO5eC201GhLSbotcAwR0pYpK2E1U99aiKS/q0O0umrudt2j/UwxzmKju0WXF
8HBvsjvtuVFGyQ2ukceo7rUJrVuKxmldNXo1eq3V7kTYiyoHzfzOaN3i5rRB3btF+9ABtte/
ad1fWHZPU0abnF7Q3ek6BVMMB3R3so5hc9sDuztZRxmULDyxu5mdNyej1M6xu1N2PEB5mxMb
wu3ummvsxL2sGOiZPv4YTKXZG71phaXQgkT3JifuYjTkfvKl6rBvHPQeDkvZTbjdUjT+2GSj
ENKLEIHtsCVkJmTO7S4nhod7k8W+JM9z0UCn83Zwu6VonKW13EicdZcKT1HEqNNMRPdWN6d1
sSWNySW80R/Ov6boXvkK0T2wb7HuHvUEGUrACzKAB3+TEGBF5X9P7O4cZ0MNu07sdiZccMM4
x27dXyqcqKLlvRO8e4ergn67J3br51PXnQNFs05sSPl6kue8HCzoia2AJJbaOffas6LkXkJs
yeilRXnHUJaisS+aenEtaGMqHc2Sp4hJLxplQlCWouHE3tDSjNwLlY6Vr31RBN2qk3mTy8Di
UTQ1qeZ66E7akwZK39uiCGY/a5RYisbFAN0kxeXzFJ7QiBIDnEwUr4XjE8XMRaS4GuB4jxRv
53ffJQbI4B37xO4lAZwGgRezE7uX5old1UEaemK30zy32oJpnoP37nBLaI7HkVs/25CEWnod
0BCCN0l2Xi4W9MRawD6ZUbtemr3YOziqYWtCBk8mnl5rwRhVyzLEZ1aHcSLYBStia17KkHeH
7lI0dq2iWnqp3LJLCoP8LuJBK1knuc7Lw+JRNNXNp5XZVpERVnDiLcR8utDtrPfHYjTO1Jq4
Iamb8wyCFWMi+F0Zk9H1pXCK0VV/uRSuY3RY7Hlt1u/N734DLcCs4GX+xO4mdm6GjhI7x+7O
3wmh9mcHdi+xq5Lw9vwTvHeHje4qqvd4YPfm7zRltE/xxEbQuzzJqlyGEfRExX+4t52KUlNF
ZdpsTUyb4h2F+FgMhlIvub+sIppWuJQd8ehMBQHXouGXcTMR9epNl9hvgUNaSAvddsL9fNB+
PIvGTonqE9LVncoEzMz7opC+volczFI0LvzSpOU22Oc1QLYaJBczTd8thVOS2huqcav2A8qo
gcJb6jmO3n2TIqCAJOqA7u5VRLP8B3R36q4q2qt4YLczPMloCfkE793fYawIrdAe2L0Mr9vh
g2o+H9iQBN6E4V2OEfRExl/sNS2DWZlEC+h/IUGTKHKnYP2xGI2xNaqNBhU/qWCn0wi98HmF
dikaTlxI1SUb7flBxTtTxJNmFO+ORfx80n48i6Ym7W4/20ulQmC92Rd9NcVbiiankUWatjo6
cwZtcGxVRHp1msFbCqe4nSmzcOPMxODBuuhN8qZ436sISA1Njh3YvQd/8YQX9vFe0L3EjtOo
aIvngd26uyyJQCfMA7qbFnc0rfiCbv10jYzmgnf1ExtC6Sa5lMsqgp7ZeHQyNtJVhnJtoGlP
DAni2zLmx2I0lMiIYrNFQqhPBIV03NW7BOTnYigl9dpa59K6FAIpgy8K4XN33ZA/H7MfT6Mx
gu2KhtRcBBJt6gpJ2RFNtMSXosmpF+nVHc1yVgXlt3PM5kwni5fCeU0W26+/GuceDJ6n78ni
v7YU4ANa17fTOk5ZUTGFA7u7JmtXbLCX7cDuJXY9UQblG07s3u9vpIx6Wp7YveQuG2EDM7In
NoBDzDzayuUSUZ45eBgVItVu/IRrQcldRP7baNh9n/taND4GX7sWtRN9CKP5OgqQ0KNX+eDm
0F2Lptj5+ZLzcfHdDAsCrunv/pFCyP01olwmEQ/3Rnlw79qMDjGq9BmTr6N8P128Fo0ztWx/
lazNQgLfBGH87l57cnVzmkeiUlstBayTrI4ivfndNwsCDlRD+cDuztcpoZ/vwG7P2MHunwd2
L7HzkTqs7HZAt2fsGph2eUG3Z+wYbOQ6sSFtdvelsXJ5RJQnwv01cdaRSevQnMG+Rlv01Rm7
tWheGTt6tdpRVlwyJiRp1+6LsGvReP5tSGlaepWGvuiC/DtmpO6yiHi4N8ou1NiMOnTOaEI1
hNS99NjnT9qTaP4fAAD//+x9y5ItOW7kFw0HJACCNNP6minzMzSz0ELqxcz/m4ATjLvosojr
wWYyb1Wdlqxq4+xOHEYEnXi4j6RdDJZ6QEWLEpy0W1Ihv5GMmd0ciaKCae1VX+0Ef2PJmL+J
HGA20KVgYHcn7QSsJh7Q3Sk7RdUUB3Z7yk5AS+CB3Z2yK6CywAHdnbBjA4dkBnYJt7suk5XT
JaI8ke7nJP7gFc1qTQ20wotFX52wm4omcm9hReCUiDPqF74sYXfd9TQXTUkSOi6UqXXVjDa2
r7jl3HO70yTi4d7ERAiF4E6pBDZHrxEV94/DDbebiiZYmpPu0qxVp90d25xF3I74Km//Ob05
3ISUau5U0L76WPRX5Hb8FXKAYGPRiovZn1h4z98nWJElsHv5JicWUEJ5YLcXiQVNth/Yrfsb
IiuhngorsgR49w7XjDoWHtitf193Hl5AzeaBXdIDeJNRPE0syhNnAYupdspOBbI5v8G4QCxa
wjqvm+3nosnO0yTX3pqz/Maw/dWKT73ZTZl4KhpNHgYXKc5rMjd0cretEKG+m9wtp4fFo2gk
UZYm4bVWnHRi0cSiFdHcCLPMRfMSZqm1+SvDMaSCss4lwixCN2XiqXA4kRWOXoROLYO+cTyp
EP67s86/lfBeRkd3D+xeEhCaJmAHxsDupnkdHbcb2M00ryZCS1EneDfN0wqOFw/sXpqniQjV
Vz6wS2jeTXLx9LMoT0wGLAlXLkStNidIWKre1hAj1Zvk4lQ0OXH3nzqycaVrQ2neCh+i3Pim
mjcVjd+uSDNTqUX8JcQ6NXXJGM7t9G457SweRRODuIWMyV9VRp0XFg3v1usx8blgQl6ZqlBT
7rUTLq+8oqjP9Msn7WE4JfVWJYsRKTdDWxTmtK/fLO83kN+DSy8Du5vekYIWtwO7m9455YXp
XWD30jsOfQ1UV3mAd++wEw6wb+HA7t1h4jBPBAnyAC+pHl/Ls5TTpKE8Uc5vqRCzdHNa5HQC
VuBbUz2+HrKciyYn7c3f99qdC2dQTzA7j1qRx6s3x+5UNJH+NQk14t46OP/qa5YMFNwljE+L
hkfByEuiKLdGjUtvWN5rjWj6rTrLXDRO1Vr1SPw/rRBqarpIgI/69TTvXDgcOVaqVTSGpMDy
BE/mWN8E7/cR4IuPJcrzAruXBVjy2y3IAg7sXhYQ2RF0JPXAbuZ5LamC17UTvJvndUHvkwd2
M88rSWGjhgFeksi7tjcop1lDeeaj0aW2Enah4QaPqvCtcNnVS1/aj8lgnOaJqkajIJhj9RUr
Qrmt1U6FEmVX321/sM0/X2BNZVmt9uY2cfo0PIqGk9Pv5rH43pSKS/AtsT++I3lT0ThdMynF
fF+cfkvBst+x6quzeFPhlPgEdPNjSMLTGU3iTb03b473zQp89YECX/0GBT50rmJg9576/n0V
7IJ6QLfursbXH8zODuzeX6+lImhx+8Bu/fuEk7MGcKb3wK5gdHdCLac/Q3kims9JSy1qzM7o
GOxZ4yX2qlnrjXzGVDQ5Zc0vvTen0YyaEvqiJZm7m7aoqWj8o8W55yzhJNbhuQ9bI8R3c3c4
7Rke7k1vYb+lteRecaGWJazuMqv6MRkNpepsW4VCX5kY1ATyVUuGcsq15uPs5ihb9msnkxLe
0zBn5fmmdb+FEJ+hSbEXdC+3U3/vwbvFC7q7MssVfEVe0L3MLv4nwbr2wO5mdmjh5oDu5nWV
wFn3gV3AHW4F+E5ThvLMxkAk5hG1FD+eKlqLWdNyd2M0PxeNU7TqUWTr2S9KYGUpFq1ouZOb
OtlUNCU0w50LOUmVDna7x5oVzOFunPe0ZHi4Nd0JnQfjfMgYvbEtkmq5bGT4mIzGCVqlXtgD
yq2WjlZk12zO5XTy5/TmaNjmUG6htArqsuZJa5Y3rftm/T1DhxUO7PZsXQUv5AO7O1vnLwrs
mBHY3fk6Q0VaXtD92TpQFvcF3c3puIK5zoH96lzdacxQnjlmaIgql94q5QIO/S3L1d1wuqlo
Iu2mGuVkk9bQRtc1nO42VzcVTdjE+03K6Xb1Y9zQutiSgcxbUnf6Mjzcm+50rigJESnMG5aQ
updv0f2T9jCayNWV7teHXvkl5I2SuiVdg3e5usnN0dLYd93YPBg4Vzf1GXiTut9Afy/SIKBA
6cDu7r8ixvvsA7s7X+d3U/AjdmB3Z+ykgSmagd37+3U/ddEWqQO7m98Z2sI1sF+cs+PTmIEf
mmaURuLMrknv4GVklWlGve57mosmqBrHUEjOYeuFcog1/E6vovmcjKakqtxKtLVrtOyjSbuv
5nd8+jI83JsurWft7N8SdBQzL2nkvE3azUUT6Td/wqjn1qoIOF++IWk3uznOuE1r9VtKjJij
/O4vOUbxJRp8Gax85hVlzz+zCh/qlziwe1knp0a4Rltgt1eJUau7gd26vy9hPUFp8QDv3mEW
VHf8wG79+17KeiBNG9gVecWboUo+vSP4iaB/COqZdfWLo/UGFhF80QpBE63X07tz0YR9VGNt
WSXXAusLL2HRd5Mdc9FE620WyyFkjQ7bbxDh49M54lEwoacXGskmVXIHCwa+aIn0s163AM5F
E0IrNW4DnWojVVie5atF+ObCCT09iSq+UnWSjlo2vkX4ltG7b5neLSmjdHhg93KAOGfQ3OKB
3c3y/NIJs7zAbmZ5Tjw6mFw8wXt3WFJp4Mk2sLtZXkhNoCwvsCtYHl0xCT98TxcJfiLtb0mM
qWehVk0KqrW8Yi4pq15PesxFE4StZfPjl7uwoNXjNVrLl3q+n5PRaDISETYyzTmjIny2QHHG
T/rrSQ8+TSQeRcOpl249O+dqncELnC9aMrdyo7U8F00QtlrMmoUvhoDjyL5qSTGcrptP58IJ
Qb1uXJx/U644zZt61N407zdQ4SsZTPAP7O7acc0Env4Hdju/Q0+XF3QvuwtZPVTv4QTv3l8B
S7MHdO/ukh87htL3AV7B7vLV7d3P3NOtgZ9I6Dcn7rnVmEikLAVV4Mtrcng3qZWpaHJSK9ZU
6yuFB6uzrOCqdwp8c9H4pSp6DhqJahdw9ikWfXUS7zRreBRNSPAV5dYyCVfQpikWreCqN+os
c9EMdZYsyqVZBu95i9RZ7iT45sLh6K6qnZWtlSYwu3vP8a5id98kwdcLSKIGdi8JaIlQpeUX
dC8JsORfAPCMObCbSV5L1cAv0wnen6QF/8CB3UzzIm+IlroHeEmp9ia1cro18DMnja49dN60
+L/AQVhb0pif9bKp7mMyGmdsrUdGMvshbKhYUtIVpNXqTRJvKpoQIlCPRkuJkUuwn3fS3+Cf
aZ7cNKOebg2Poom7TvYlMToR80ZoEm8JL7qjeVPRhGYyx1hvEev+jYRF+FZszp0I31w4h5VG
KK37vxQd+3xbaawYAdmvwkfYbf6A7u7Q8gsm+Pgd2L0Hv6YGy4Ad2K27q/75Bz+tB3Tvr9eS
ors7sFv/PuEkqIjRwK4gdXdzH6dDAz/TzVcmJ4u1OxsiMD+0bK73pl42FU1O2Uirley0TipK
6lZku27neueiible59old5ZIre6c632ZY94/aT+e7o0/YuS0IatzrA5O7K+hqJxvegCmogk1
va6SiWrnVsBHbdncx/Vc7+zmqL8uvYdcC1qSmBQkf1O630OBj8A5shd0d92uKahi8ILursqy
dLCp7cDu5XU1mtDBbu0Du5vZNQUnygd2N7MztOtzYBewh9uJ3tOXgZ85GfjtnJWkR9NYRp0M
ZIlhxo1iy1w0odjC/v/auVs2tCq7RF35JaV+ddxORVNStdZ6LqXWXsED1xct0SO+m+g9bRke
7k13MsTcnK6SgdqpeU26rlzmtz4mowlmV5vmQlRK6YYdkzuY3eTmaPHNyX63YymgONBbseXP
KcPn93i41BnY3Qm7Ar5NB3R3us6PSfDqc2B3p+sM7WYb2O0Ju4L+fgd2e8IOFDE8oF+drjtt
GfihZQa36BaSIpxBFs2TWvl/IHXX4mhz0UTmTRs1f9ctOu5QUreCcN+m66aiicybFaqRS9UM
Z+tW0IY7xww+TRkebk03ao2VxR8zeGuWcDq+5Nsfk9EEp5POIX1NRKIwp/tqx4zZzfGLkPVM
fq1jAtVF344Zf2IVvp6IwJzOwO7O2HW4Fntgd+fsBK4mHtjdOTslMOc0sHt/P3+m0I6vgd1N
7jqBc7wD+9U5u9OdgR86Z3CjYv5t78ZgjWyDc8ZcNJF+a7V5SCySUdeaVc4ZN9JoU9FEzi4X
a9yK/wtsGIxFX52zO90ZHu5Ndy5U/Gdq0iuajl+lwneTs5uK5pWz0yIWaihGoLrLDhW+yc2J
zH347vmXSkCnx7+qCl/506vwPSIqIEdZ8IlcwIa/SRuQGfydBnZ3mjPcr9A8Z2C3c+GewQLa
gd171zFNx4EHTXQc4L07LInRufaB3fr3Nd81BU+NgV2S7LyZKz59LfiR2UBNNRToWmPysxBu
uVgjDmg3JGUunCQm2sgJZKmotmReI4LzGuG64ihT0fh7J5GpE36Ne2J0OBatSHfKLx+1H8+i
acmJvVGY0IZYK/jupBWTWvcTJ1PRxIhwfaVti29RA3v4aU04pd0MN02FE4n17jevbCGuCcrG
zGbWf3c6/PdRB8ypZTBnN7B7WYD6W4bmZA/sXp5niWBrqwO7meeVGMFEed4B3r3DLYPVlYHd
+vdV/00KKBA0sEt43tVx9e8sp7+FPDId0NS1CpUw61DUEUIXTRbb9RDKZDhJMzVt0qVkMrR0
Ope9+ee0J13zvLloOAYdupJ25SxgNLwms5bll4/aj2fRtKTV1O8U/ZX3RKWKVoj73PK8uWjI
vzmhdGgeTxYuaNqzLXjUbnLSn5PhvPpIcy21kLLCyktzPQdvnvcbyANSB7VPBnb38V8Z/PsG
dncizxpalD2wm5sW/EbJKH8a4L073FOoqsJtFXVzWbvZi0pgh9SBXULwruWf5TSSkEe2GJY4
iqZUW6sEyra9Fi0heNdti5Ph+JPqxxQTqxA4WBNrvjiPNxeMJifdFmbI/gEj8NCNRUv43S+f
tB/PoonGYguPj5a1N3BMqC0ZZ/cf77ptcS4aZ2pa1N/HmOCqqBdyrFoRTvvlo/YwHL+C1vgC
lGrlwTz7HPl+87vfSCCwgvXQgd3du9gYJQEHdnceT1CBxYHdS/OceVBFad4Ab/0FowsAFfId
2K1/n1EiATPdA7uE5l0VOP3wPZ0k5JEvRvhXO8HzE8tKbyAxClPpBeFIu67XToaTrPcioqrZ
MjralNoCY4xs7Sa5MhVNWJmRUyLf99YYK9cusj/L8ssn7cezYFryWKjXHDJ0CvZitjWklfiX
D9rDaJywdSffkpms+8UCLdf2FRYs10I/n5PhlETEuZTmd6PewftRebt8LKB53yAQiKoXD+xe
aldeN3Xs7zuwe6mdhmsHSO0O7Nb9DdeJDI5sD+ze368lPwRgkcDA7iWePdUOJiEGdgF3yHI9
LCCniYQ8M5HQnC0SHCG9AgZU11Q01W6yKlPR5JTFOUmtysQMjtTHohW8zq5nQeeiKUnJGVCJ
UF5iv1hOZUn6rly34clpIfEomKgbN+OmVqsQ6GrLq2Zsruef5qKhVIXFGV1uVnLGp45X9Eg6
BfvVk/YwnJzEg+j+2pRitaNKMvKXnEr5m6gEVgGdCwZ2d4HWH0i4QBvY3QVarmje4MBupnfl
wVjvAO8meBU2ED6wuzOLncAdHtgVBO/SDMPP3dM+Qp5o+tdUWIuv8X8wg69UXdLMn7VeTVF/
TEbzIniSW5faSgMdChYRvJfv1dWxOxlNl1Aazq+SM+jPu2hSN8tVc+TPJ+3Hs2g4aXVu4i+q
9Woww9MlhraX0XxMRhNzx6X6h5tKLU3AzoZFujL5MhH5ORmOvwOZrVTyy7xJgeXT3wzvX2d4
27UCuYIlsYHdnblrCr5OA7s7c2fwCN+B3UztxF9LVBlqgLdTOwXzFQO79e8TSiwgdxjYJUXZ
mwP3NJGQJ8r+4Vtd2HqvxNVgA9i6Jnd3VVv6mIwmxP9EhZ3Zce7wAbVEMPAymM/JYKIfKsRQ
apUQtQalUddwodvc3Wkh8SiaSMORxyPB61BFmUW5uzt/j7logqNF010xirIBKF60SlHmLnc3
FU4O61DO0pjEXyD0xZmrN72Z3e+hGIi6VAzs7tydGKhRMbC7c3di6AjSgd1O8MzQ1NgA791h
SsXQJ/DA7s3dhfU4OL89sEuKszcE7/SSkCcC/5E4Jr+sN6niJBTLD8WiJQTvKtv1MRlNTn5M
Ua0lOyvC7QrKiuGKpleZyM/JaKKrqWbrxsJaQVk6X7RmuOKmDeC0kngUjZM1qi0bk6qhhXNe
cpUIWe1fPWkPo3Gu1lumosHyWu8ow7MVXXeFbtLEU+H4LYet+jnE0dwAd6vO3Vp/d4bHX6EZ
CDYaLWnOXjbysV2bDx3oDeRePsJ+5qF6LQd2e7W4oRm7A7v3RmGWqnSwHWCAd+9wa6Cy4cDu
3WEqqWfUOnCAlyQVb5jAaXUhjwwIahQle67snNPQVqC6pCiZtd0UjOfCSRJqu2Ewl50JoB2B
K5ohsl26qnxORlNTaUzZLFeyBvbvxKIlpPMqEffzUfvxLJqWWmfmnLt1JdC0NBYtycPdKLZM
ReP00T+LXIxVSiVQy47WuMQIXYXzORkOpxLWf7mXVjSDn14/W9+jHqvo3Tcp83UCneJf0L0s
oOKl2YHdzfO6gl4fA7ud50kDUxUHdjfL6+hQxcBu/ft6S/5dx/6+gV3C8W4O3tPvQh6ZEESO
sFBVyyXDTZirEot36Z65cJJkpdK5ammKyv9PVsD+kFi8qedNRRN6or0oF+mkBGYmdI3Ab760
Vvn5qP14Fs2rczfycCEwqAwKHq3JxGW9SWFPReNsTWPU2h+zMO8AM/KxagnH++Wj9jAcTmTZ
slQjq2D7aax5U7w1FG+7KJ8w2tF+YHezOxJQCGlgd7O7VsAv2MBu7gvwmz6qKXeC9+6wpaiV
gfzzhd27w/nVGwRu8QAvYXg3x+5p4SCPDCksCnrhm9VIMqiiEYuW9Aa2m3HLuXBSLTWUY2vt
Bpui1jWyfDet+FPB1KRmompiTlFASRBftIbg3cwXnQ4Oj6Jxgke5FcvVP3hm2OUyFn11Em8q
GqdqXSSbsFX/D9gkHKuWELwrzcTPyXA4FCBFS7HOmcGmWp4U03kzvN9Ilo9BHjCw22kAgURq
YPfSAEtCaC3vwG4mepoU1XM9wbt32AxVrDiwm8u14VSN9oAO8BeXa/X0cNBHwvr+txk7obBe
nXiBQzd1Uln/n4meXqfyJsNJ2jXn7r938x8LYxN5CZvIVq+Z3lw09SVH081vqhy+cCDTWzFu
VPLltPLPR+3Hs2haEu01mGtVzWAZoS0ppd8yvblogrMp5dy0EIlfLVAB5hXE9S6VNxcOJ6q5
tNpCj8ZAAeZY9GZ6//IUyHZlPoK9tQ7s3rO/JPPXClbmyytG+J4q86FF2gO7dX9joqN0dHx2
gPf+gs05OWr1cGC3/n2iyQ9d7A0Z2CXc7nr8Q0//Bn0iqh85H2KWEMrrGRwiXZMoylqvc3hz
0eTkfNGPKKnc/R+ot8YSP3S7rDl/TkYTwgTZXu5pXFBDq7LGviGXqy7Jn0/aj2fRsH+Gi1kt
2lppDa0E2orxjzvplrloIi+fLcgd95JRy99l0i3XSby5cOJ600kzca2tVLSFdS6V/6Z2v4U4
nzVQMuAF3VymBSu0u4uzMR4FdzLxdr1l8eszOrs1wLtZXUOHZgd2L6vjGEzA/r6BXcAc7oZ6
9XRr0Cca+v7w+d+WOcYsjcChm1j01axuKppgddwzFaLauICC4r5oSe/dddP7XDQl1U61iDrf
JrReFouWdKvdsLrTreFRNJyq3w2t1/AXI7QgtKRs7qzuWrZlLprgZ9I4eiNzlVdv3z5WR+V6
qHcunJy01J419+K3CFC8KU/a2b1Z3fcK8uX6wEqj7rfSaODw1QHdna4zQ3nTgd1O7Ax1Cj2w
u2kd2v4VyN2JOkE7Kgf2qxN1p1GDPjPRqGy1tyJ+Q8+goFhdYgbglO4mfTIVjbMzI2uktVR2
bodSuhUVZbs0Wv2cjMa/WNYjiWpE+mrmwxJ1S7rt7hJ1p1HDo2gi5xbC112LkBQ4UbfC643s
KrP1MRlNkDNtwlWaWlPwUVukxHebqJsKJ3JupbP6Tah3huW834m6FZTum5T4sqD2qAd2L7PT
aA6ClfgCuztphwqrH9DNzM4pRwUr2Sd4N7fr4D34gO5O2FVUs2Vgvzphd7o06DMHDaFsOVtr
xYqg7E5W9KRpvUmjTEUTuTfyM9eUnReB5t2LEnZ2l7CbiqZEqU8Lx8FbFSxclkWVvsvR359P
2o9n0YSgXqdqqh4S6r4ZWb4lCbur1tSPyWiC3VEl4ey/FAnYk7YqYcfX2jtz4eQkvfVGjaIj
I8MJu7+kIMqXqPBldHR/hZ7Rn1iHT0D/9QO6l3FytNWiAh62QjTsYZFYwM/qwO69T1hLGR1L
OMG791eJYIWWwO7d4aDhDZV5G+AlOcWbwY7TQUIfyfpboty5iB9l2hWeRlrxg2fVG9o5F04S
bkSWSwn/V1iHb4kzb7vJ9ExFU6M9I8ZeexA2sOpd14xC3FkE6ukg8SialhpzmK40lgb20MSa
FaxTr2ZuPiaDoWTRYcpayC9rWeEJ3jUSLTcjRFPhcGIl8ZuNNCMFDdtj0V+Rdf69ZPhAm50X
dC8JsNBXh6c7A7ub5jW0v/wF3U7yGKzcDOze3RUnRWDn0wu6meCx38PBnPYJXkLwrr7sfuqe
BhL6SNW/xly2f91zVCcLnAafSyj8QaLlZp5yLhynRLmHNW+WnkFVk1i0guDdTe5ORVP9alW1
+4lbnOCBBhLLJnev1YD0NJB4FE1LVlioFtVmFRRgaouqxneTu1PRhGSyhSsTvVQSGRbhW2FH
J3RVXvicDIeTx2D+JbDmYYEJeZ406H4zvN9Aha+gNdmB3Xv811QJPI0Gdju5E7CqOLCbewJq
6hUdkhng3TtssEH0gd27w9lZW0bTtAO8guKVm8rxadegj8wn/PLDnKlklYJKW74WLcnh3Ry8
c+EkdXanJLk2BrVvQ9BlBcO77Nn8nAzGH+yw03Ly3Zp2wd7XWLQkhXeVkPz5pP14Fk1LNexa
QgPk5d6CqvB9uTbLVDTO1Rq12iOfVqWDhJXWaGDfWWnMhROuGN3JKpWSTcDaXeJ3W+AqgvdN
InwNHT0f2L0soCV/JHEZmbLCm/yhCB9qSTawm3leFOjQUugA797hw1sT2+HAbuZ54biJKvEM
8FfXak/LBn1kQBFlV2oc83zE4PzHslrtZXXzYzacVHMVFdLq5zBcq13RhpbtUjv6czKa6OMQ
p6yq0rOB9cBYtCSVd0P0TsuGR9G0pEzO83yHujZwLq5Njo0+IXpT0ZCfe+Rs2MycGxW0Q3CF
LVEpd0njqWg4hR+0+WsTsjNgDsUXTX3U3kTvezX4cgPvjAO7u00rC+hjMLB7j/7Q1QM7aF/Q
rbsbY7oqcI3xAO/9/fyLLqhE4IHd+vfJS/kWHOw9sEuI3U0C77Rq0IdWDd2/550bRaUJtWpY
Ikd8O9g7FU2I6fVei9XWraHP94bB3qlowkM5hP2sdRLURiMWreB1d4O9p1PDo2jYbze9OOk2
8Y8x7NSwRoEv33R7TkVzOOMUKqVRNVAqesdc71Q04SRjuXJYtvj1Dp7rfVdoF/C6bxLgq4TO
zR7Y3RW8VkEhyIHdXaNlAUugA7ud4HX4ABzg3QSvg5OmB3QvvXNOruBg7wu6gEDczfXW052h
PnNnkMK9FHN6HLINaBP/kqTdjRDfXDQxottfQ8qtZHR3lskrXyft5qIJnSmtxhqeJgVVp1qT
GHrloe6ftB/PouFULR6xIj1mYOC53hUNa+WyYe1jMprgaaVoL90PvlIrxlU3sLu5cEJemSkr
hcSywI2rc3e8N7v7XiE+FtRe/sDuztoVcLT3gO7O2VlHe5gO7HZSZ2hB9gTvz9qhvnIHdnfW
jgtjWcWB/eKsXT29Geoz34zKmVrrzXkQ+oPXRV139VpGYy6aSMCJUbAHydVg34yvztrNRVPC
Sk9r65lV0AqKr1nSdXc9wlNPZ4ZHwThF6xyGJqSNDGxW4TVy0XcCy3PRvASW2ZwJmd8k1LYK
LN/yuqlwImsnOYx8qTCBA3ezptFvXvdbqPERo2OpB3Z31q4rqhZ4YHdn7QQ1qRzYzQRPEze0
X2yA9/6CPTFKQF/Q3Vm7Cp5RB/Srs3anRUN9Zp8hlP3/ahxWqCDCMjW+G3I3FU3wtDjKqwdE
paCiYmvI3V3WbiqaEvLrWqWIxeUKK/uVNW37d/YZ9XRoeBTNyz6j+DXWiAqBY6aL7DPKjQDP
XDSRf4sBEYpmSMqwJ9qSCZEb94y5aHLyVz8q5l2Locw7Fv0Zyd0+6vZf//jvf/z/f/z3f/7H
//o///f//cfW0wnsZN3MiEAytOBrvIB2f4ccodSQKYNzRoHdnVPlDlbDBnY76WawU3Ng9+5v
S72B78HAbv39aknRNYWxwAO7d3+5pgybdg7wkqzq1ZHrdOg00qjPjDS6H7RZWnYWgR65vmiJ
G3G5kkT5mIyGU8htFC5NMhv4AoZi6YJo2o1K3Fw0LZXmWx4WfOFAg12KYtEKcqe/fNJ+PIsm
J6rCtSmpaAWJdyxaEQ3/8kl7HA1r0R5uLUUZzt/PKfj9c5L410/aw2j8hdZGOaZc1CpYLPJF
U3vz3cT798qqfqMeobxkQGCWF9i9LE9TI3DYemD3sgDzcx01sTuwe/e3p9rA2v7A7mV55J8d
cJR5YPfub+mpow2vB3YFx7uszvrJe9pp1Gd2Gp2oM1NX6hUVqfRFKzje5azsx2Q0nFQ7q4Qk
YUgtghxvhdCBc7xrwZq5aCxpq1rVmX3mzlhy1ZbI79xzvNNN41E0QdcKN2d3NfeGmkAt4nh6
w/Emo2GKXtUsJTe0BhmLVqSK2y+ftIfRRBo/xAyEmjoDRyer5jITb4733YqE5lunoOz7wO4m
dzWj0y4HdncKzzI+7RLYrfurkqyD5H1gt/5+FhpxYAZmYPfur3AqsA/gAC+hd9c6wPW0rajP
zASKNefGpWqL/n1UanZJCo+u6rMfk9GI/2FCNediygWdR1oTTcs3iZWpaFpSCw2hw4kDdHVs
kxXNP9TOb7o0TtuKR9GEnwZnJiGW2jJcbl7iwpHpZrhqMpzeJJM6tesN16lZkfsuZNdOdnPR
5NRrz6H3xVSN0Pxq/1MWz39LfvcdOTwLVxhQXnxgd7dHopowB3R3Bk9Qz8cXdC/F06QohR/Y
vfk78YMKnLwa2M1VWkuZUNu4AV7RHtlu8iqncUV95ibg/51Vw0xAGVQI8jUryprKN5Omk8EY
RSdhe1Ej8OOwRhQlN7oZfZmKxlKzksU6+T9eDntQAm+Fwc6NdN/PB+3Hs2iCq1nplaWHqR8o
phDeHUvCuWmPnAynNSpd4p+5Kai9EKuWULyrm97nZDg5tdqp1C7CWkABnjz5rL0p3jdKEUoJ
LgQ2aB3YvbSuJEOHIgZ279GvCXQ7eyG37m3piTtI2Qd262/HOeGORQd269+nPWUGE3cDu4LU
XfIgP2tPr4r6zHgjBpkrW6RSFOy2jUUrWF27ynR9TEZTEhGphHFurxmVoPdFK1hduWF1U9E4
3SyVfNMl0miEnbS8ykfkWsm8nlYVj6KhVFvNhfx+IzmjU7O0ZqSZ6k2KeDIcE+pRNfed6Rks
zMaqJST1KpzPyXByCg9tiaGkbgpOz8eiN6v711ndt/TdRcUGLH0O7O7SbAa92A7o7sKsgF0/
B3Tr3jIlXAvswO4md1LBi8XA7iV3lkoDv+gDuyRjd+3oUE9/ivrMbaOVEFLrrYizCJjcLVGr
kRtyNxlN+P+G2F2PyhVcW1qTsrsZM52KhpNfWfy/t8TkLDe0g1BWsKF8OQL880n78SyaoGlh
d0eaK/tFApZlXqJXcynw8jEdjhXzN4aaP21GYPmD1lDv6x7Cz8lwcghqWVOu5BGBNnGx6E3u
/mVyt7nbPqbiQFPDgd2dsgsrajRlF9jdKTvr4MznwO5O2+UCMqeB3c3sakUtqA/s9rSdgC1D
A7uE2d0IiJwOFfWZb0ATIdUW04xowS8WLUnb3RRjp6KJDJxUap2rWUd1rDak7aai4WQixYkD
x2wm6sm6JC+UL6nDzwftx7NgnKKZOW0IPaRSGBd3WVG85MvmwY/pcMzfl64ekuZewUdtR9Zu
KhznaKatRLOHx4QPAL+zdguI3Tdl7cBZzxdyd8ZOOqihN7C7c3ZqaK/9gd3N7RpqrPeC7mZ2
hB5mL+jujF1G9RsHdgmvu7ZzsNOcwp45BrxahUK3rwl3MMPsi5bwumsJwulojLp0cT4Ux+6X
tgr9YYzi+rCdi4aTKPVQhquaGbbakCVzBzflWDu9KR5FExTN7w/dir+rSrY3Y6fXdr+z4Vgo
glIh35xqcAJyicvdXcZuLhznaLkUy7VJ0QZmh2PRX5HYMUzsHvWNgy3jC75Fy6Y79gvwCeg1
PbB7CWeI6qGq3Ad2N+FkRk05Duze/Q17NwGvEwd26+9XLfmHHHxPD+ze/ZWcDq93aHr3AK+g
nTd6xHZaZ9hD64yu4idoUa6S0ZzVkgTcy1/3igtMRSMpSxUVyqy1gA+QL1rR03g3vTsXTUtV
OPeWc++EdgG2SYvYB+IsdlpnPIomdFaY2Pxp672Dh8sicZZ8uTcf09FImJpQbiXS8ShNWzFg
WORyFPlzMhp/oaux32qrP2i9oRccek92rKJ33yTAV9GS2MDuZXn+v9nB+cmB3c3yuqIfsgO7
d397qhmVsDiwe1mepo6mZQd27/5yTwZa+A7sAh5xJ8Bnp4OGPXPQ6MU/79UPXz9+wQd2jT+a
H5E3+Z6paDi1nqO8arlIBYXEYtGSZsAbjjcVTUtFhn5OqVxAw4K04ktyz/FOB41H0bw4Xmh5
SeRJd4ssXwu0zEYjOYxNclPVjI67yoq8ItO1PstcMK+LXg9tlsyMml/PXvTeFO930N/LYLvd
wP7b//4fAAAA///sXV125Dav3BEPCAIksQE/2PvfzwVaVB5ujpQSQ9P+Jp1Mfh6KM0ZTLRbx
U7W3ZGwd5XYHdje3a+A96IBu3d1Q1AN77Q7o1s+uxWAEeK8Y2M2tnpw0o8IsA7yE2V33aLXT
oqE9M5xgZ+09PDT83Q761sWiBdHIpcXy52Q0kio5X7Ts8SiBFwNftGTMQ6+tYueisUS9+/Zw
YW7Ov6FofNGaMY8bZndaNDyKJpRZPAzO3blDZXA+b5H23jVR/ZwM56UU3ar/Q+rBgK+CRcnI
G+O6uWjYn5omfnFk3yO0oM8pv7ndKm73Q9p7DF4YD+hegucHu4Eq3y/oXgoQcnpoR+CB3Uvw
NCn6kh3Yvak7SwWd5hnY7RTPrzRgBX6Al/QF3hy8p0NDe+Y3kXtvOWcqVgvokLZMfO/m3J2M
xnqxQlKaNXTQuqzxe+v5et5jLpruVyuLX9mf7wJeF/uqkYJr8b12OjQ8iibIWs/+kOVewpAP
VatbJL53U6GdDMeksT9mYWGnpWNnUfj8fDfHmwrHOV7r5F+dZlF3Rv0z5jyV3hzvZ8X3KupL
NbB7md2Dn49/4OcLSb2Cmv8c2K37+xLVQ8ULD+zWz6/4eYu6Bw/sXu7p7+gKWqMM7ApmdyPA
105zhvZMMb+rOu1UFlICE0ShwbokeXetdTsXjVNo4d5DfK9lAwcSY9GCaJrdTHxMRVNSF+NO
PVe/moJT7Uu0ETlfCtb99aB9PAsmBj66GWfJVriD2a5V+nuXPPVzOpzmW0I5N+JGlVFit2JU
6qbK/DUZTk7C5lsjHJ2rqGxskqnujDex+xX6e4VR39sDu7vtjgrYNjawu0uzaNfiAd26u6Gq
h2YWB3Yvu5PEYF7sgO7mdl3ApPbALsnaXevvtdOWoT2UyveDlvzAzVQKOIiwSn+v33C7qWgi
jVCdAEsLzQkwk8JLSpn55SB9deBORRMGILVkslwz7GG4xgDEyd3N3PhpyvAomqBp3Epv1kia
Hxa/htxNhuNk3uNQ6ircGKNDseq7yd1UOM7TSEqvKsUJONwQKe/K7L8nd9v191pHR2YP7O6s
XdQo0KxdYHdn7VoDvaUGdnfWjgxlxQd2e9YOHdke2L3MLqRhwJ9vYBewh3JpEOvn7WnN0B7a
ZoiY8+JqRAQOzC7S3xO79pifi4ZT1jB7D2nl2kF9WF4zMHubtZuKpqReu/Nfqp0bPsa4xAzt
ZSZ+/6R9PIsm0nZEzQlEpIca2LK/SIDvltlNhuNkuzQ2v0M40QJ59w5mNxVOpO38plXDK7oL
enC903ZLmN0Ppe0aWAk4oNuTdqj87sDuTtopOo8ysLvpXUfp+8Dupne9ot1fB3Y3vcsNdG0b
2CWJu5t0ymnO0B4aZ5Aft7VlP3sr6A7ri1bMIGi/oXdT0XAiJVVuSlIYVehMKyQc7xN3U9FE
4q70l5lqzg3sjo1FS+jdTYr4tGZ4FE0QNafdXLmWzhWs/++gd5PhNKeqlVrc3DwyuHtwjRPx
Db2bCieHaFhulZVyFjAN+acm7r5Fhi+DZZ68pMSzbNRjvxBfBrN2A7uXdvrrtYL2UgO7m3b6
4QfP8QZ27/5aIkL398DupXVOdQXs9RzYvfsrYQYBNgMc2BW0806G73SOaM+cI17uqObXnsOH
HhNnWMI6L1Okn5PBSGLLlaxka5RhFT5eUi6+G/KYiqanGKs06xLDouCNoK8yBLsZJzp9Ix5F
EzOsYj2uBV062Du3SqGFb+43k9FobqalhB+voYQirXjJM9eb+81UNOXVZlFzpp47Gk2ZbLP4
7Zzzv6TC1xqutRzYvRSvJUV/voHdTfG6ovn3A7ub4ilo53BAdxO8AmZSDuh2esfwRXGAF7CI
Ow2+flpI9Cey/pxMoujVe6bmv1ANviW2bTc6y3PRSMq5lCa5FmapmOBELFrB8PRag28ump6k
WOMuEVIFb2O+6Ls1+PppIPEomiBrVEicF+WisPXKIg2+ayOZ2WikvzzOeogvVpSvrtCrZ7Jr
Eb65aJysCSn7JSVaHEHV6Fj0ZnhrGN5+ET4GJykHdnfRWAyd5D2wu6ld1BRgFT5Z8RJ7KMPH
YNFzYLd+fs1S6yA1HtjNPZ+hS4Sqbw3wEnp3LcTXT6uG/kxAn6txLq36/azCCTxe4Xeml5oz
n5PR+KMaU/tFuDvjB40nZEkpL3e+LuXNRWPR49icEfWmCpq32ZIWx1sdvn46NTwK5qXDp5mb
SUzyCux2tkSH73JO6nMyHOedVp17q1QTA1sc86Ry3d/o3c1FYiqakNSrzdlq03gNoO0Wc9ei
N737PTp8RXEhvsDuZXk9vmTg5MKB3csCWop3GazFx7vFljWJgnojA7uX5XEyNZDlHdjtLA+t
Ag7sktbAm6P3tGroz4wnorrYpLy4Edp9tmK8O+ul49PnZDDiP1jlLmzN/0tYlkjWyAre1Wjn
oul+d1HJtZVeuoEWsH3NaEHWa2Ggflo1PIom2JpauNpyGMyCkiCLhPjyPz9qj8Mxk1pqb87t
CTXSiFUrwrkR4psLJ4bhW6lC3V9WAt4nZofh3yTvZ4X4nMbDQnyB3d18l9GRyoHdfPBHtRXV
4H1ht+7vS1xPwVvagd36+RWNrjBQq+XA7q0d58SojcbAriB2N0J8/XRq6M/MAJw8qIpQbmHY
gM58rJiS0Msh2M/JaDixH1C9kRg1uNDMK0qzdxO9c8HEJFMYo/VuVAW8RJQlGom3Qnz99Gl4
FE0Mb0SuS3MI8jFYad6g1TIbTs9dWbpWyx01j/ZVK9rv7kY+5sKJ4dzM1Sldt17xUvN7oncB
sfspIb4Knq8Du7s82+DE3YHdXZ71V/IDJb4VYnLP+J3fPGF+F9i9/E6SodpwA7ub31UDvx8D
uyRxdz1p2U+bhv5EOj/E+FphcY5H2tEa0xotPrvJpkwFwylzCJxYFlYD09K+aEU0nW8Sd1PR
hFCC/67VCVFrFbyLlUWZrhstvn56NDyKJphaDodlJiEiOHH3/fxuMpxOWokLZ4rxJHSkd8Uw
/D2/mwonFFv8PeA7w/HQgeeWL3rzu3/N77Zr8flhDmvxBXZ34o7RxNjA7k7ctUZg1/2B3Z64
QzWWB3Z74g512H5Bd9O6wqD/yMAu4A7lsq7kp+3p0dCf+mf0mjn82a2Dp9Mi/wy1m8N2KppI
wfkFJGsrKmRw3m7F3tzm7aaiKan3HjItLEUr2KXmi5aU/G6U+Ppp0fAomsjbOa/rqlIJVU/f
oNQyG03Pktm4Z4vBZqz2v4PWTYUTDK1y8dunckO1Mt5pu/9tIT7Bjq8DujtpZx0sGg/s7qSd
isFJu8BuT9qBsgQHdHfKTqzB9hmB3c3tOoNplIFdkrK74XanR0N/6J9BnYm6H7elFow/LJPh
u/bPmIsmWobEnwWN9ifUiXTWu/NJzm4qGn+nFm091NGyGCiNVta43uZ61bP/15P28SyaoGnO
hpTCxZcq2E6zg9xNhuM7Uyu1XmqIifwWkeW5aJym5SJOU602Rj0fY9GfyO34O1T40D7m3ZVF
kJ8seEEu4ME/pgyIvXsP6O4MZxjeoBnOwG4vXcMewQd26+6aJGWwE21g9/JMTkLgu2Ng9+6v
P/NWwdHsE7zgZcL1pjnx9LToT3wGNDWlkFqR2iqDJUVdMu+Z9UawbS6aEl0qkv1WGTMt4NhJ
WWLdmvvloMbXZDQ9mWSPwpxuGYPq7H2JqM/NYMNfT9rHs2hC9zvMRtToNayxUSyc6XIi/3My
mpyKVjLKIUpNjN4gV9gisNBVC8vXZDQl5fBZNw69Q1S2sUyOa/12IvxfkgYU2FPuwO5leRpz
dyDLO7B7WUALRU2QBBzY3SzPUE+Zgd1eKX5QKF5RJ36yu8WSNLC/8wSv4Hh0c/Kexhb9idmA
Jg01XhGuxRiU0/NFSyrZcqPpMRVNSdpb49JyKdnAk9cXrRktvkqofU1G01OuIdhWpWqrYO42
Fi3Jdt7cJk5bi0fROF2TwmqlS4hzYz0TPClA9zepwxuONxWNv3NytBk0adEJgpZ+V9xFudCN
OOBUNCURkW9NayUzujex6M3x1nC8/eKATWHZjsDuJncVtaYY2N0pvBg7Q1N4gd26v5lKMkXH
YwZ46yfYXoOv4BN4YDe3oVpC+3le0BWlbL1pHjv9I/oTVf+amFvvUpSKgY0XvmbJ9MmNtcdc
MJJCWbhFhiPE7TA2FIuWVLJvpDymorGkzropU/YDF4vFl6zJd910TJzmEY9iiTY4f8hIoiVW
O5rvmmuDe6IZMxUNJeutiFQOYcAK9qIv0oyRO2o3FQ6nbESs4cOoVlHa/U7fLaN2PyQMKAQK
BA3s7lbFXlD9mAO7O30nBez0HNjNDE+SKOouN8B7E3iSLKP2bQd2M8MrqYK6EQO7IoEn1/LP
djpI2BNdf/WDJxerzJkPEwQogbfitMp6aUb3ORlNSY2LFj+ynPI3hRv8Voyi3GkDzkXTU485
FAu7M7aCve76d087/PWkfTyL5jXEaqqtV98ifNphScpLr2neXDSU4mJUekwYl1rBtvlY9a0V
9K/JcELlj6twLr0KKiz2VgZcwPJ+QBkQNVYY2L3Mzv9MAi9NA7v53Hc2CQ5svqB7d7ckP/pg
XaDAbv30Sk6tgs2VA7uXdYZRB0iLB3ZF5k6uy7J2GkfYMzn/1gqXsMAIjwL0fb7EBkP7tWfb
bDREVXN3TmL+u6MDxks8hlu/zqjMReNfOyshpWfirwdYOGZJfohuFCjtNI54FE1OFK4xuXeP
CuyK9DUrcndFry3b5oKhmLmszrmJ2Q++jk7ULBkQunag+5reG2nNXvbc3Qr42p11oHuzul8i
C4iqxxzY3YXZDJO7A7u7MCsZJHcv6N7dlfgjQXJ3YHeTOz+dwQnjA7uX3PntW8Cq9sAuSdnd
kLvTMsKeyfi3aAzPRUKrDTtyfc2SAWO7brmbCyYnYxHW5hFVtGM4Fq3I2NFVNvVrMpriW9PI
nKlyFJvh/OOajN0Ntzv9Ih7uDbFkE6s5FA6xaGLRimgupXA+J6OhcLEsrXJzUk9aUPGYtoKr
3g0Yz26O+G9KxKUbKa75/O65+/fkbr8mIDov+4LuTtj1jioCHtjtCTsCR8IGdjdnb2ihc2C3
p+waOEoxsNtTdh2Uoh7Y707ZnX4R9sz8ws9YZeq591JBbZIdKbvJaJyZtmbW/ehzDvFrUnZT
0UgoXeamVZpEIhLsHZzrb39C6063iEfROEPLUYM1J0KKis0uo3U3Jf+paCL7Ruy0WzV2HrR8
3pGzm9wcf8aUaiVtrYDemLHoTev+Pa37KU1AUB7ogO7O2AkqhvKC7s7XqYI3nxd0d76uVHBM
ZmB3M7ssYB/OwG79+dScEoE/38CuYHZ2c96eThH2zPeiNuvNst/TG6rswktk2rLeqFPMRZP9
Cpe5MGvNWUHlkLyk7yn3y4rf12Q00ZhJlDUGKVrrqKpL/faE3ekT8XBvKEtl7i3uEGCGKy9h
3Vwux48+J6NxjpaZxYjCdQ58z9OqZOpNanhyb0qtfiPyeKQWsJnTF/2RxK58hyBgBZMAK+7/
y8Y7Nnf/aTKYkhzYvXSzvObiYfG9vOJYeUY4S0bPvAO7dX9DaqWAsjEDuzdZ1/zejYo8H9jN
yWJNpYDGhSd4RZG4Xs0OOBU4bSzsibeAph6WwGK5BSPAItIlBqdZ+SadOBWNJKdoWfwT75ka
2H8bi1aQzrtm+6loLKn/rrV6OMyv/gBsfHdFAu5OfM9OF4tH0XCiqiH+83rYUE2tRAsS1zf5
t8/JaCKVVmKyo4ZNIXgUzebf/ja9ezNBNBWNH5HOOLN2ziEChAoazV2kfzvp/E+J7yn4yh/Y
vSwvNE3ARqyB3c3y7AHLs+0sz3lHBfU4BnYvy6uJwDP6gG7meOwXG1RBe4BXcLxLSWI/eU87
C3viMaCplqq1dephUodyvCUXYKWbdM9UNDGOxI00fgkYTKxZkle8OXingrFEEkS1CBOh7R22
Rq3uTnvPTjOLR9GEVHIhf41QoyBGe/WVb0Z3p6KJmeK4o7RexAo4TrRoEFkuvzZfk9GUxFZi
PirKxgQ20MaiN8VbQ/G2a+9VA7ndwO4uGFtHa1wHdje3awqeLgO7dX9DbKWiKdATvPUTbC0V
BrVtBnbzDjunVDDJfYJXFI5v9PfsNGmwJ9L5NbGoaKbmZ3oG3U590Yqsl1yWwT8no4lHtVIx
kWZMoHSOL1oy6XEp4Ps1GY35ta+QH7lFtRn4tMWiFQQv3xC806ThUTShpuebwupfhcLgjJkv
WiOufJWR/JyOhmpp7F8bK5xBGbNYtCS/ekPwpqLhFOqItZQu/iol1IJxzpz1TfB+kQJfAb+I
A7uX57XEqAb0wO5lAc48wPm7A7qZ5an/maAMzwnem8OzJATu78BuZnkS3nYgyXthl9Rpr+pN
fvKeJg32RDq/vs6qrlKLH72gP3Ndclbl1wzk1ck7FU3IlAiZVj+wKiz0s0ZNsOcbjjcVjT/W
lc3ptwj1Bk4WxKJvTXv99aR9PIsmOJ4YNf+gRAvMipbILFP0u90/aQ+joWR+M4qUV25SCCxt
+qoVOcnM1y5pc+E4X3v555DUlgV0DfdFUy/dN8n7WQE+RS0KB3YvseNUCzjiNrCby3epF1BD
ZmD37q8kUrCDbGC3fn7ldUZjB/MLurt0zIzSzgO7InV3N817+jPYM9n81tmEc47LO2g3HItW
0Dq7OWwno8kSxUw/nWJoFDYBWJGIbHajnDEVjaTcfUuqEwe2AiciV7znbpJdfz1pH8+iCTG9
SKkW9X86OGm9SIHv5aN9/6Q9jIZSmMSS9bBoqbVjXxxaYrPMdNfpObk5qhqGM8bFn2R0c+aE
sd607rco8MFqHoHdXp6taOvdgd1dnoU/v4Hdze7UUPnsA7uX3UkqGaQbA7uX32koE4NZrgP7
vfxOaFgzxP884ncsLboDWiYmWK1lyXjFdWl2OhqyGqPJzoi4gS6+zu9W9N7dqLVMRuOXqjDv
zRapFOzIlUXqJtcTvWcsH89iCdmVzpVVi1UC6dD3s7vJaILdZa5d/GZUGTfNaEu0ry/7b7+m
N0dzbUqWi98o0GrO5BzPm939rAQf7Dc2sLuTdqjb0QHdnbJrHSxtDexu0t4VJXUHdjepI/Dj
O6C7U3algB2fA/vdlC6ftOGpZ0bT8IY1ZgMz9KtSdnSpqzwdTdYewmjW/HQyOGW3Ym9uUnaT
0Uhi53RSfF+ccIO8IRZ9N6nLJ2946plRWm0UHr4VdRNaRVFvSN1UNEHPVKtaK8LZQA2d70/Z
TW+O70oLb5amig8Az2mLvUndrxDgqwZqZgzsXm4X3T5go90LujthpxUsFw/s9oQdrsG3ZBLg
WTG2VzRdd2B3c7tsqLjygV3RZXfpC+snLp/84ZllRjXKtSq3Zgw6GcSiJem6S42K6WhIpGq1
kHhBs9G8ZLj0Pl03FU00GdRaqBOZofTh+8WVz2g+nkUTanpW2Z+14g8aboj27dxuKhrndi3s
P7rVIt3AWjktUSW/T9hNbo5mcbbqlwnRBr53Y9GfyO2+RYMPvZvlufGUP0eFD9WwekH38k3n
GQSqwg/sbsbJCqqfDOzW3TXxzwR7tRzQvYzOUi9gHWlgN+eKo+qLVSAHdgnjvJzdFSonq3mi
4//qPFWWVkLmDWScsWhJNvHSZGEyGklsmq1ZLl0a+PhIKmvEWW5SPFPRWFL/2jkRaFWbgV1Z
sWgBqbnR3zuj+XgWTejvFfOrV69VssDiLEumVC4p2udkNFEeJSnVL2m1VFgmeYk24o3+3mQ0
JZUoeKuWbqWB9DkW/YmE87+kv1cFTNkN7F6G11Il1BT+wO5meB3VZ3tB9/I79ZMA1Vg+sLsZ
HtxCObDbGV6u4NfjBK/geHKpsSwkJ494IumvyX+yxuHuUVmxgzfWrKB4fEPxpoKRlDM1Ja7R
di+g36QvWkHxLl3BviajsZRN1aiLddge0NYUjG/0985oPp5FE7nbEPJ29vjKku7V37tJX09F
k5P0RsVJXnRpoiINSVY0AQpdzUZ9TUbjbI2rOL/LVJ3qwRLLUxe9N8X7Bfp7MZeE6u8Fdne1
WMHX3QHdzewaLqzcNusqh5yeZpSZDPDWz69Z6qg818Bu3t8WugzoDh/gFd2Ad/k7PQnEE+X8
mC12CiFmfjtD/TNi0Qpy1y91WSajkRCytEYvtqpg4SsWLSF3N92AU9FYMmtW/ZwuoYoG1lhp
Tcn4RnzvDOfjWTiho0fcujQRLbjlxBKt6GthluloMlFoXmvcLFHj9SWzRDE3/E+P2sNoOJXs
RDX7tggV8I4Xi97sbhG7+yHxvdJAFjWwe0le9+8LeCYN7F4a0JIUBUu0B3Yz0VO/taHFhQHe
S/RKItSHbGC3Ez1Fpz5O8JIk3qWJhlA9ycQT/fz6cmoIxQnO1MGHtq5pplO69DaYjCZkSrpl
f1yJq4FPuC9aIsB3V6idisZSpW4WpMi5EVhEt1XuvJcCfGc0H8+iCS09lV6cR1QWcJpwFc/7
5yftYTTkJFylhN9w8f9huNNxCQm/VlmeDCcEk4uHY9WjKYyadL9VlheMfWwX4GtK4LzHgd3d
f5czWF8c2M31u9RRiZGB3bu/IaoHjssO7NbPr4i/OcGTeWD31o9rEnCg54CuyN/dTfO2kzo8
U81vvUa5TMRYwBwRL1GayGo3xdnJaKJxjEvxeGo12ANgRXH2dpp3KpoYzKUcUwVEtSrq5rtm
mvdagO+M5uNZNKG24i8Rro0KKz7x8e0SLVPRkL+wu0rTpiYk4OgcLTGOvp/mndwc1ejArZxb
NdA84z3N+z8twCdoamxgd9dnO0g+D+ju+qxQgQu0gd3N7SramvSCbmd2GUzaDexuZqcgdzig
383s+skenknlN3+ZSyvmfzHYirFMeu8mjTIZjZNUlVDF4d5RQ52UV8yJ9HqTRZmKJq5T1sKO
lFVgHdRFswh3s7z9JA/PHDOIe+1O7koztKlhA7GbCoZek3rNzKlqaRk08d0h0zK5N3p0ELIq
l4xq6Oi77e7fE7vNZ35JlEHH1oHdna9jAfNNA7s7X9cqSDkHdvf+9gq+XQd2L6vTFGkKjNUd
2O35OgNp0MB+N6+zkzs8tcwoHKomXIlBI4Nllhk3x+1kNMz+IVWJ5JCCblu8pn/wZTRwddpO
RSPJN8R/X2lOiBgcz5Yl0dzzOju5w0PLjGzduYPTbjWwrLxDo2UqmsjYlW5ifnswzmCPWqz6
bmI3uTl+c6AiypmF0Gbxd8ZuCbH7oYxdE1RS4MDuztiZgPqpL+jujJ0yqgt/YHdn7LTjdmiB
3Z2zU9RneWB3s7vKcM7OoQv4Q6HraYp8WjLkZwYT1Zr24ld1yxV2y1ghH/LSXrk4cGeDoVBz
8BOqqGTw5hIWGyuo3Y383lw0EuVLc/5QSUoDnUdlVZbrmtrl05LhUTQvapdVqZVOvaH1vm+n
dnPRkN9uQjfE/ArhfBU03tvglzG7OcpsTr2JMnfQHfpP9cvg/3n5vUcsBSQoC16RC4jwj4gC
vrSbwTTYgd2d5hS0cP2Cbi9cK/i2f0G37i1LS34ogZ/eAO+lmQUfiBnYvftbupNbdDR7gBe8
TPhyeNUZymllkR/5C6izDSLLWVtDVZhei1aQ4Utm/zkZTkndL+St5WySq2JZ2/DQWVK/vnJN
+ZqMpidh0VajqbpncLwpFi3gW6+e7/tH7eNZNJpKDeU5vxWSGOgB44uWiDeX6x7YuWiy/2Di
T1huvkHW0D7LJdEUurl2TUVTkr8DSuv+L6kdVAOO6uafyIX/U8qAHfWRO7B7SZ763ZHAjMaB
3UsDWiL0Uv+CbqZ5mjLYijKwu0menwMwyQvs1p/PIv8LktCBXUHx+IpF+Ll7OlrkRzYDkooq
dVJu1FHS6ouWKANe5tQ+J8MJzyMW87OqdKqgMGdZY57yelleHbxT0WjSYmy51FyLdZQUrTAG
4lfq+/5R+3gajXO7qpnJ/FYBquLHoiUU71r8eS4aZ2seDRVmzb41YNLIF63Ym8toviajYb+z
1UxCWp3jwS0gc5n1N8X7BcqAvaGSHQd2N7erhHO7wO5O4VW0AX5g97K7mhMTOm8wwFs/wRZu
LODtYmA3J/Fqkga2Up7gJfXsG4Z3OkjkRy4F/v1Q6TmbEwlG7Q9j0ZJmxZuK9lQ4koRLblHP
5gaOf8mSrFd+0eOrY3cqmJ6iUZE8mNy0gi9kX7TE3UNucning8SjaIpfc4S1dJEoA4ONKmu8
Sq7L85+T0UR53u9Exiz+/gb9MPJk1uv/R9NuCN5kND3sqHsxQq3xYsmb3i2idz8kDSgG3rMG
dne3YmdwWmZgd2fwBL3YvaB7OZ72VCqqrDjAe3N4PTEqDDiwe/eXJPUu4A4P8BKOd8Uj/OQ9
LSTyI5sC/9lyC905C9dqcMJQlihh3Bdqp8IpyamqcmlSrKEi7LFoRdfipSPG12Q01TmBComf
vKUzaBpc1/T55cuc5F+P2sfTvXEu5H/nmDcuoPBsWWN6RjcK0HPRUDLuIdnIaqxUsM3xVWta
Sq/ViubCyX7RadGwwTVsA2F57nca71/zvP3KgJXQFrwDu5fbhRohWF58Qfee/OFe2sH83YHd
ursmcWbAxryB3fr5FY6CMHguH9itP59aUgOLmQO7hNfdjAic7hH5iaR/OGqrRWmmCoMNa75m
id7zpT/B52QwUWNqajk36qxg7Xy2xvS32uy1XepcNCW1yk5OqXanDmCLVyxawupuarOnd8TD
vWGqNTq8Wom2tY2ijZz1JnU3FQ3FgdIqZb8+UIzpo7Moa0rNN6xuKpycivWeQytduBBoOJ5k
aiTtzep+hTBgIVA67gXdXZzNYOXugO4uzQoqsfSC7iV2JRHK617Q3bSOO9h0N7Bbf76QwEYd
2wZ2RdPdjRlvPr0i8hMB/zDWNaFeTJvfLdC+rrrge+687tqwbS6anKy2QiEfI5XAiWlftCKa
fpetm4rG78rdKRBzE18IZq9j0QomRFeDCH89aR9Po8nin5E/Z0RSBfUEy0uI0OU80udkNM7Q
RNVKTCT1mkEpiWW87h8ftYfhRLG4kW+OtaboyN3sAPib1/2kLiAnZ/Cwj0dgd2fr/DACOd2B
3Z2vaxWsNQzs7nxdQ/d3YHcTu1ZBf8uB3VsppsQiYKX4wC4hdtcGbfl0i8hPJPyj1Bc5hy6U
tYBJobqkZyjrpdnr52Q0nKh1MxLRUCoFs/lpRS9ubu1a73kumpI6M9dsPXcqFeuBKmvMIm4T
dqdZxMO9YRJ/0ir71jSwqMyLfEnuxGOmoqFIprL4sRI1fwZFpGhNNvU2YTcVTuTe/D1gIv4F
yobeiN4JuxXE7qd0ATM4rzCwu1N2glZjX9DdKTvN6Ojhgd3N7io64TWwe9ldSdnANraB3Zu2
09QNzHoO7Ap2d5ka8jP3dIzIT3T8/WJRuJEfvLlSA5PMsWgFu+s37G4qGg5Vh2a1sJMhWC5p
DVdtl6mhr+loWuutapFeOprmWnHLcW53M0dx+kU8jCXXmoMJkdYKvnh80RotlBtuNxVNpN9M
sv9tpRYV7D2/itvd+DzPhZNDa8BaMX+NdoOLsfRHaj6X7xAGBJnAkpadZQMe+wX4wPa1A7qX
bZZU0DLdwO7mmwXtnRzYrbvLYqkqSJhO8N58XfeHCjQeH9jNO+y0C/UuPMFLOgBvuMDpZpEf
WQxoKtn5EpmWzqAj3mvRCtLJN6RzKhxJMeiaq1llRjMjsmTgNfdL0bqv2c0hZ2rBbnrujQqY
56E1TC3Xm+z1aWfxKBy/+ecWOTguQqiPgK5RFKRytTmfk9HkJK0V7S3m3gi8E/ii752t/pqM
pqQwK4wyPnFF51RKqu+U4iqC90MafLDM/Qu6l+f5Hwl7ChzY3TzPHviN2G6/kaBuUsEL8Qne
y/Nq0ldGAOF5B3ZzX0D4ToONCyd4Cc+7rufxaW3Bj/wGxL++tWZ/wTufQCf3fNGSWY+bucq5
cEp8m1SUa6tqHZ7gXWMVfD3rMReNJa6FSVsTa0YYMYpFS2jetXkhn9YWj6Lxy0Hp0a8Z4XRw
b3zRClXB61rr52Q0+aUHRLXl5owYNFzPa0ir0LVMy1w0JdQ4tfl9vlOwVvB7M1dwetO8X6DD
VwmW4asrJAGeVY0NraW8oLvZXVNwBnVg97K7qqnDgzIDvPUTbC31An6CA7t3h1tPnMG2xRO8
hN1dZ1b49Grgh0YavWqzVjM5A8UHz1fMSIhdZ/HmwpFURZsQNTIyxpIRskZRsF+mvb5mN4dS
DYs8f0GEpzM4O+aLlsgs87VpC59uDY/CKcmvEczVahFBu35i0beWWz8no8mJWkySlKYto9bh
sWhFNO164mMuGk6i0mKGl0pXMIsXi970bhG9+yEdvixgFmVg9/K8lvyJBNtMDuxmHvAagEeF
+AK7nelpQeu1A7yX6VFiRZUgD+zmHc6poonGE7yE6d0kV07LBn5kC6Ap1FqschjvwkRvRaoo
vw6Uq9N3Kprwzg1vMY2OR1K0XEsrkpL9MvH1NRmNOQlnK8XP9S4C1lVi0Qqep9ejvXxaNjyK
xilboSKNRFk6OJ0TixZEc+26/TkZDSWr/oD5i8f/QxnUOopVC8LhuzzeVDicitRoQSbWwmCK
hyfdQd5E76eF+MAK1MDuJXf+Z6JGSAO7uYSXUEvBA7p1d00TgfJRB3TrZ1f8qGVUHvfA7i0f
WyoZFYA+sAuIw91YL582DfxEPL8mIpEuhcQKg1+mWLSC1OVrc9K5aEITxNiimlkFHx1doQkS
bXLXJ+1UNJJKax6Mb07tDBou+qI1ox/XZi182jQ83BuOdk8pksOxBZ3qXaNGfMPppoKh1KxX
0VKddGdw4ppSXzGjnMu13/JcNDl8upvfhnrphGci5/j2m9L9DhU+dPpqYHe33xHYi3JAd5dn
hVC3qQO7m9kxKokysLu5XVZwxGJgt7cGwtzuwK7gdjeupHy6M/ATyXy/U1APt3Yj7Si3i2L9
dDT/BwAA///sfV2O5DiT5IlGIP2HTl6gHjJPMcC87i6w938Y95BUGHwDqUz8mJ5V1dGFbvSD
qTssqJCMTnez/znUe52ONscm3FeIxIq5YGVBBcQSy5beri1b5tj4lkVVqPjqaGFwIMEv+mqP
ZTrDGR6uTR1tRDlIxiBCh5S/3LJljo2Lu27aXXPzMKqg11FIwhV06KY2PEWnbso8qnXpvjtC
rca2OaeMt7r7Zi++ihfsAptdsDNGE5h3bHbBzgZcsLMVLd0PZR06mXpgs2UdNVAWH9jskp1W
8KT4wH51ye6MZ6Annvm+4WH21xLF89wG9rJta8Im2qWN78ckm3AEGUJDhhQbYCrxGkeQ+5Ld
FBuJ3d4gGaHp0JNLmbRHeyLrznSGh2tD5JtrbTEGDJ6zbCuSGO9F3RSXV8XOn4kc5sou7LCl
ySjZTdGpW6vDrBbfNwp4n0WZ763p/n1N900Vu9ZB+5gDm16xA886d2h2xU4FjOM9sNnSrqMD
Hwc2V9pFcw0airZjc6WdbkyotNuxX12xOxMa6Fl6hvmrNlwg2VURWMLVJYUHl3Y384tTbCLg
zP9yZafiEgKu2K0QqnYn7abY8OYUNGyjVbh11GR5rAhouJV2Z0DDw7Xxzb/LEr/ThPCKXV1S
4roTd1NswlJv9BE50WUM9EXkV63xFbx2RJmjUze/04TqqI0KevBfN/0rHVG+xIivojYEtOL4
YNmMR3L/X0y+gl/Ugc3VnOw/YHRfumOzVSeBh+w7NHV1SYvv1cGX8o7NLteNAX59BzZ3da1s
DbWqPMELHiZ82TXnWuCMj6BHnv7hjlZHV6vF0Fyw10UrDorvKopTdCRsBUslbdKsghZTa1wF
u12bP0+uTfHXei8cRja9ga4ZcdGS+NpLEf3zVvvxjI7fNFJtaCMbXMBp8bhoycnqdezzHBuX
XBQuNlX78P869iyNi5ZsCW42OFNsXuEN1FTNtDEaqeQX/Y2q85/kw6foa/bA5oo829TA7ekL
mi3xOvjpdug3SLwHCi/9PNbQiYMdm7y2bWP0RPIErxB45cqyzt+6Z4IEPTL2l61z5WbCGlFU
qANfXxLvceO0PEdHInm7REejKqPt6nHRkk7Am/asKTav0d3um9M4yBugb/Sq0d1L3+ift9qP
Z2x0YwsRIfIa84Ad+L62EPcxySYKcRyHxjyowI5cftGKtbkxWp5jw/F6JKahcIk0LnnLuzXy
Lt1/TzvoEHxgsw+MFXTF2KHpuq7gB8aBzVV2MXcA2jwc2NTvr7uaLAP7/g5s7vr2SNVCg1IO
8BJtd9MNeAY10MMUjd64Fwu/DDTZ4HXRCm3Xb2xZpuhIfNOltirVIowO1HYrDvJqvwnmnVyc
4nu+3kyZySq6OH7RmhHeG/+9M6nhER3emkX3XBs0BI1BiouWtNBd7Yo+JtnUrRYZfejrlBU9
qPGLVkjVyx/O5yQbf4VX882QdCVWePR9rhb5lne/j/8eg1ZcOzRX4/WtDDR+c8cmH+FtImg6
745NV3mGnsCf4NRv0G8qVbACc2CTV9g2LWAN9AQv0XnXhRU+gxr4URiAbjSqNuMqMdIL2++t
6A28O6SdoyMbucjTQcUaF3hQYsni3KWlTS5OBJ9JFem+kRFc561JS7vReXxGNTyiEx28NqpQ
KWZjwIlcS1yjb9pQ59jUMIgIs0eVOjoq81Y4HN3aLM+Roc1XRRpFi7oM0NGbJjNB3jLve933
rIAFvAOb3X1X0QrUC5r74n+ZX8CtTH3Jt/d0mBf0tzuwqd8fh+UfaNHygubKzrDBx559O3SB
argb5OUznYGfWOa3rZB1cx1UBrfkOd7rFvw5MuSCrlPV3qgpKzrHu0bQXZrVfU6ykejADx/B
IUUbodZ7cx34D6z3+MxmeLo2XP1bMisaq5TrvXfF5mOSTdn8Piut+C+SuhL4lIqrlizOjaKb
olO31uTV3ukvoY4GPk6GmrwV3W9hvidgdtYOzT6X7QV73u3Q7HNZQR1uDmy2rLMK5nkc2HRZ
h/axHNjsnsDxwFZ5LLLe0ys15G/cM4+Bn5jk+46CRnNl19W4KqbtdE3DXSs3b9wpNuTbNxml
8rDqIgK2VV4yyDuuT8rm2MhG2qtoV1+dXtHkjzWRtzeDvHzGMTxcGyqug5hFm6sItCD05dZ7
c2zCb8UoDMmry27C1qYssay8NWmZYxMmLaX0OnyDUlHLmbjoLe3+bWmX77yn4E7kwGYX60jA
kZ4Dm12us4HOZO/YbF3HBurOA5tfrsOrddnFOgL9/nfoVxfrzjAGfhiUwUMiHiqqXOAMRVuT
F6bj5j07xSaqdWOMPnrrvcB+vV9erJsiE3W3ob21MIfG50HWjMjeCbozjOHp0sQkQ2uF1Ao4
D5JguzfHJrRZq0bOplZpuO3elxfrpui4OFN/+fi+U803WujE77tYt0LRfVOxzlDhdGCzy3XD
wEfegc0u2KnC9TqH5so6f0GDB287NFfUydbB0tEOzS7VEVgo3qErZN2N4x6fOQz8NCODerdw
e2YCvcl1iSts9CNdv22n2NBWi1L4oBH3itaC6hrrkxtZN0VGttqLtqLdxR14oBzXfLWqO0MY
nq7McOUQIy09HAR/mzLdFJswU26N/SJ1Rgw+pBaZKctlsvXnJJ26aa+jxLxyNAKhLYI6dat9
t6rL02z//z//73/9v//zH3VFK+WT2UNs6jBZBoESaMGTeIHW/g63QSvR4A7OsuzYXKUdzrTo
LMaOzVbaDN9mAU1dXYrefbCW8YKmfndaN27gS/nA5u4ERjTQYp/vwC54kNR6M8RyxmPws9QC
6dJbFddz2sG2urhoARu53Dt8TLLhzYnUFt92EQMVKq9JG7abAdI5NrTx6C7oag8jGvA5tyi5
5NI28eeN9uMZmbKxSGtKxYZZAQs4cdUCOnQzqjxLx7iYxPlDrWrgNjWuWkFHr85SPqfpqDYr
pNRGGQKWUf2qdxl1lbT7lmHlsg0CLUwPbLbC69XAzvUdm63w4Hi/A5ur8XSTAY5TH9hcleev
KwUrfC9o6qeTunW0BeLArtB4d8MGZ04GPwsv0NLCNa2NoQNuelpRvXaNd+01OMfG5VoptTgP
GtYYTf1YYRLij5drP5o5Nn5XW5zEttKZK1jooiX6OwILf3Wn/XjGxuWaDi1KWka0pWKL41et
6OQsv77VHtMxjkp3bI2sNPBcyq9aoVlffs/399pjOjr8QdBZm9904HM3LnprvDUaL7fA010Q
oRFrBza7A7KCrhk7NFva9QYa+RzYbGlnDZxrObC50q5tIuA49YHNFncG+mjs0AXygetNVeUM
o+CneQe9jCL+9jOBHdPmkuT/VdrZtbnvHBveWMz/+JOoSAGVt1+0pHx3yeZzkk1Iu956bVL7
GAWd8V0k7W42EWcWxSM25ZXh0qjVymrok7EsSXGheqm7P6bp+MoI1V6klcFgw21ctYJO/+W9
9piOFtFmZioqBtbxy18aUPePMRsMG1y0O+LAZks8tICyQ3MlnoXJNjjismNzJZ5t5eU5j3x9
OzZX4tlGClZnD2yuxBO/48GTmQO7ROTdVFXOPAp+lnmg4R9rXeRJL9SKA2e5tEv7mCTDfh8o
i3BU8RS8u3nJrG/tdnUM+DnJhvxrdi1kzdQGo7vZTZdEEF+y+Xmj/XjGxtUaNWaXJ1TKaGA+
tF+14lCztpve20k6bdTWyB88Si6M0CPnFZUGYr5qbvicpqNSC9VRVNtQ8L1aJh8Eb433nU6D
3XfC6MnTjs3VddFxBYZJHNhcZaeb71Th4eXApq5v7VtRrPduh+aubnMpDntcv7C5n8+1WkFT
pnfsinPZm2QuPrMo+GHcgapW6V1aR5/nftGSnJC74t0kG/MboRWjJiHvQDZLNLfxTe/dJBvt
xYppIRlo3OXsAMK/HmTexA3yGUXxiI1LNGOtY4iWiBpDXVyWhMBdd6t9TNMJBVTF3ysxJybw
SeaKY2a+c5CepVNdbrPTGczo+ONsovRb2P0GhoN9MwFL6Ac2u++uwq6kOzb7cJYKmhW2Y7P1
nb8JwcPjHZu7vhYHwqCC2rG5n0+30cHRmQO7pHJ3fWgmZwqFPAs6qI27mT/ZW8OnK5awaZcq
4mOajVXWUQuLuW5F+whXRGzXfvPWnWXTSoTASQnPSrBMHBctUXi/vNN+PGPjWq1Hjyf7XiLa
tFENwStqXXRTJZ6l4wLPN0XM1dR/P/B55grBypfT2Z/zdDh8qlzbEcd+AqUzVVh9K7zv9B3s
W0Nb7g9sdulOGH3179js0p3vUEHptGPTS3cVnerdsdnFu95QX8kdm128aw30kz6wX1y8kzOP
Qp6FBFRVLqUN6xGv8bsU72bZmL/2nJBL6cHgmX5C8W6WjXaqUsKRIHKLc4t3V2x+3mk/nrGJ
8Yioc/GodQzGT2WXRNlddjN8TNPxvUOobqfjG3Nweq6sOTNnvYpN/JynU/z3X0hdrjaDld27
drdA2X1L7W5spGCn9YHNrt2JomezOza7doc2yuzQXHk3ttLRlLodm125Gw8qdyO9chdLhp7N
7tgl8u76xEzOSAp5FhTgkjHcxzqTCjwzuyI+trZyU06ZZGOlN1cPSiwdHMtcVrm7bnafZdNq
EWlq2kUUPTdf4RV6X7k7IykesYnKncUtxk0GPJS5qG53UyKeJOMayBfF90Sj+3cF96gtOWi+
jPj+nKfDStXM9Z3F3faPbrljWN09Ma3FvtMVVbI/2IdPOxiTfWBz3/nhoIVqkh2bfloMa7od
m7q+JL5mqAHtjk39/rSGrRo4yrtjUz8fW8TjgJMEO3aF5rzxaZEzNUOeRRloGTyGv6MiTD7Z
p+Xai2+OTXjxFQpREz3rA3RN35bsB+zGkHiODfljIZQNDesuCcAf60YrZFq5ic6RMzTjEZuw
1es0KrfIuoZD3VYMWrtKuyrBfUyzMZJW/FfTqFYWNNFkRfWaSK9nimbpKFksTLHCr/3G+6w4
V919mxUf6NZyYLNbsgpsxbdjs0VeBztnd2i2xOuGNrTt2GyJ1xQ8lT2wuRKvR4809tY9sEsk
3rVfi5wJGvIs10BMo9fbGil1NK1qkd3yzanxFBveSguB1yPulsCuJl6Sdngv8abYhMRz9U1N
1NdIwcT1bYnp47jMVP55p/14xibUWrg+imjrzLjf8gqNV278WmbpmK+OizzfTbAQp/otl0uj
xM9pOiqu7cgfpNIGOgrwtxYW/xFefP6khL34ApvelYWGjr6g6dpOQAOtA5ur7nTjAmZNH9hc
def/T0zaOTBd16Gl4wP71aW7M6pBnsVoaCGTEWOWRKin0KT91gOPljk2HEqolz7ib1erqEfL
CiXU7do3Y45NSLTRmpTaSQgM5V5UuquXa/PzTvvxjE2JxwdJDdPHIIXRWeTDR3JzYDxJp7VR
h6+MdLYCZhH4VUuaG/vV/u5zmo5ETrT4N0Wjo/n0ftUUnbeu+318+OAT2gOb3pUFpiHt0Fx5
Z5sS+PEObK6886+kgz/lA5st7waDR1IHNvXzSdlKB0vHB/arRd6Z1SBPczTUGo3RK3VBu+i+
/nx2ig1vNcYjuvTCQxgrRcZFX128m2ITIs9cfffXpARqXbBK5N0MF51JDY/YhFwLhzdu1e+4
gudorDjRrDd+LbN0mplr1khatl4InWBZYrZM5aZ4N0lHut9jo5A0Vob9WuQdpPHvz3ykG/EJ
OD+2Q3NlXdiPorpux+YKu7DWA1+TL2jq2rqU7KBPwg7NluyGbikObHbT58B7Pseaul29OSU7
MxrkWX5GFXgcvq5pTrs1ZplkYU7D0Kn5NXMdJlf6+nOahrIMePh4RYhJ9Pb/6pb68YzFa1y3
0vCHrcTsQO647rjZJkzSiTH3qqXYEOug68+icV26nLb5nKYjQ6uvulFlfZVnMTrvoIwF2u27
vPYI9Jk/sNlHr2IVNOzYsdmHr/4QAx/KOzZXxvWtMfj9Hdjc9e1bKWhQ247Nvv+inAW3JtZF
KbdXXeD+3j2jGORZSkbVqq0Sqf+E0VZQv2gBm1tDlkk2xq53exyNET5/vKLd6V7ZTbJR5ghS
LeS0YLm9ROGV+ss77cczNjGxSzxKiXO+mHZFFd6SctZlL9rHNB016dzH4MLCFRWsa7z2xk11
bpZOGSQaszqNCCwFvx1Z/kyvPWpgB8SBTa/PDVA6Hdj0+lwz2GsvsNnSrhawBnZg02t04DHg
Dv37K3R3PntnEIM8DsnolUcPK1g4/WyRhfJNZ90kGytWxEyVKprtl1Gwm2SjXDrV0aq66oZ9
9pbIupuQDDljGB6xiRKc+u6BOXoeBRzOWSTrbgt3k3RUpVo38+dib2Agy6LCXe03dt2TdGS8
LKGlNn+Rgxvqd+HuDzba6/5SAh2EDmzu+1W3Cp++7tjswh1XPCQjsPmFO3Dy6cBmF+788QkX
7gKbff+hzey6Zuay0vU7V88QBn0YkCEuhBr71qxoQedhl5zD3hXtZtkYWR0kry4n0Kg3oWg3
y0Z9WcilQzjtgQ/iNbnDt0U7PSMYHrEJnVZivJelMGwXtEjdsV6ru1k6EWrbzMTv49FBQ9Wy
xuP6LgJtmk6tOlyr1j6agnv+v7Vo9yVGe+gZz5rznWXzHPlWewPzMdih2RWd1tA50x2brTgF
HUQ4sKmrGzoI7S86sKnfn9aNCRw0ObCpn4/bNgw8UDmwCx4lXK9dWPTMh9CH+RBkfvOVFrbI
4O99Td3qdpBjjg1vlbiFV1jMPoAH33HREtV5Pa07x4Y2UhdoUYZTrqDPR1y0QnVeauifd9qP
Z2zCT0W1aIzacDe0eW5FZAAxX7H5mGbj+5tijahGjyNaglviwfIaELy/0x6zUVeyg2yo0+qg
EXFc9Tdqzn+S0Z6BXiI7NLuoo6hZ04HNlngdzNveodkCjwdYUjyw2QKvCWjyeGBzBZ5tAzQc
3aFLioo3L90zH0Kf5UNoMQsT5R5Heck+yjdFxSk24ZfXqKrUyHYFb26/aEUSya28m2Lzknda
pI3SVHLlXb1snft5p/14xibk3ajNhbeqyGip+o74eo5olo5x8V2RDOlNDR6OWCLw5LLk+zlN
JwrYQ2s0VlnFi4pvk71FAi/dZE8Id2EJbK62k60P8O1/YPO1HRqEvmOz1V0kcsEH7jX5QDa8
VcCdxQ5N13agyUcglxTubo6LzxQGfZaQIS7oYnhvUFQgUPvkFWzubPbm2PDGtVd/zZbKRTv2
tuUlJh/11bd69badYhMiTYb5lqUw+hReJuyuAzL0zGB4RCZc9sTiqLhJNwbjPuOqFXRuDFhm
6TTrLoAiXaYN13aZBixMN5W7SToSHYBsroGHMZiUE1e9hd0iYfctLnvsmg08xT6wufqubQN3
7BjJ6jOc8xRtt9uxuequbQSKzx2aq+3atht3IOJux+aqu7ERakF9YL9a4Z0hDPowIGO0NkoZ
0aoFElplpHx3NDvFJuzyhhQaTVq8gVEj5RVs+qUo+pxk42qNWZvLk0HFQGOTuGiJxLu2/tEz
guERm/DYk0FORtXFN/heWWakfHM2O0mnuRIqVGLGundwGGeZkfIv77XHdKQN3000VuLq99zb
SDlN4uV77JUKTske2FxZR1sXVNft2Fxhp1sr4A71wKaub/U1g8uKOzZdtito4nBgs7s+B4PB
8Ad2xbHszSSvnjkM+iwjo2p44/feoiEK9txbIVRvZz0m2RiZiGmlWkl/n1mPSTYx9qpsrlVH
BYOKEiZ59UxheMTmNcnbKcYiQkWAu4hVsx53x7KTdFx0u7Yz30qUUXELviWnzOU6I2OWTiQG
im+JrPkeD/zpvCd5/2gLPkWTag5s9sGsEerTsmOzD2ZrA3tlDmy2whPQ1H2H5q6uuWZTUN/t
2Oy7z19W8N0X2BX6zm6mKs4IBn0Wj1FfGVuNrZaK5rkkzPJOsvGfuVrpZsUfSGjYxxJ91y+L
XZ/TbJRKOLxR6w2dcKuTre5PZnnPAIZHbELfuaoLt0f/p4EmRxmzvJN01HQ4j1GlChwnsWaU
V2+67mbZlCaRODxc5MEn53/nJO/fbr/HAu7jD2x24W4o2i+2Y7MLdzrAccoDmyvrXAwZKJwO
bHbhrnfwTPbAphfu0HbPF/Sry3ZnKoM+jMhQkkJUCinD0bZf7qs8y8aIubhSbWqksKxb03N3
U7abZKNMYxgPq6yaOcjst8PNieyZzfCITcg6V0GVhNhiBBiVdUuOMC9V6sc0HVUdrfriuORW
xlZnWdnul/faYzoSmSatubSrVMHn7jv17A824BsbtQEa8O3Y3PdrTHCiB7M7NrtsR6gAOLDZ
ZTtu4Nj7gc1d3zDVAwcqDmx24a6DlnU7dIW+o+tAeT2zGfRhbgYZ99oi0nLAGWJ1RaHrVt9N
sjH/HbXzL1QRfX3ZbpKNEnWJhkiXRDCbNWW7O313JjM8YhNKjczCLtoXqQw0mWGJvqO78Z1J
OupyNX413FsrubkZr2nW+3vtOZ3CytyKWIuxin/0sSx9hQUfeIS34vTukUwBFcqCR+QCLfxN
toBtgEd0Bza70lkq6hqzY9OVcEM7vnZs6vpywyvZBzb1+1N/pzfQuPDApn4+HpsU8PdxYBc8
TLjeaOEz0EKfhAzEsIJEN7t/QmtoeMqSCYf76ZMpNrzVNlppJk2KgfUnv2iFc8zLuP9Kn0yu
zf9YGe4Ym7hoidq6OcI+4ywesYkDTwmv4yKl+O4LNp9bMX1S2nWG3CwdV/TSSPqwEg7OudaA
v7zXnq+O+g9mSBVlbeAmf7Z0+7tr4X+SNWATsFv4wGbLvF4JLIjt2GyZ1/3nDxvIODZX5o2t
MDjpcWBzZR5t2sED9wOb+vmk+j2FPdp36BKRd32g3c5ci/Yka4A2rmxhVhKjZODtSkvmPl3k
XVeh5ti4XnOVJ9Zedocgm1Xuz5fl28/ptRHzu5p6sTZAUeTXLElgq9fugO0MtXhEJlQEKRfp
ZJXQEbNFCWylXfX3fkzTMRF/JHKPcN0Gzn/HVSv6FOm6tj69OsP3E8OMxLgSfDz/Ps9epPGS
3QEjEAPstjuw2d1idaBxcjs2Xdz1B+Kuf4O4Aw/bd2iutIuqIfhCO7DZ0s7AVoodukTaXVW8
/I17hke0Z+ERXGshG5W5oU7Wq6TdzQHjHBvemK0Vcl0XxRXQl3tb4dtU7bJE9Dm9Nv4NsbZW
uwtW0Ft4lbbr18NO7QyPeMQm/EkaWWEeMVLTYQu6JWfZN+4xs3SaRe6x6zoi9mXKdI+5GzGe
Xp0xhNQfBr7VEzCS6m89y/5HGQSC79gdmi3w4gcGzwM4Nlfg2dYq6iOzY3PbUXkjsMlmh+YK
vPhGUIG3Y3MFnmwGjjvs0BXNinLty9vO+Ij2LD5ClI36YH9fFcNGJeOirxZ4U2z8LjX/lUeQ
6wjditoDLon2uDxu/pxeG5UyWMh6UXQzQWvygmu/Kd6d4RGP2MRRa6/U4gBw0ABPXWbTwf6V
zl3xbpJOJK60TsxVyytSERN4C56i8f/81b32fHW4hU8I9WZV5B3tkekhk/va71sVbHu1Q3NF
XfX9NuiXdWBzRZ261EAjeXds6upGN6KCgXIHNnd9w6gb/P4ObO7nc602QGulA7ukcncj7M70
iPYw2cNftiXiOAsTugvxixawuZtCmWXjGpVaOAS6TEVN1xdNoVz2qn1Os9Fu/qc31WpgA0Cd
PCj7X+YxN5W7MzziEZviu4EeITJaxOnAx5hz4REPzAFn6Wgr4bMSC08Mh/IumTK+7ov8nKdT
JXZ3Wlx1Ky673/YxC4Tdd5kDGlg4ObDZTXcF3s3u2OxzWf8Z4uaAfcWU7BOFx1spqELZsbnr
aw9S+Sw/lY90GxXtUtuxSxTe9fRnO9Mj2sNkD6pKptIi7wxN5V2h9+8V3iQbI7auvdWwKoEV
3go2/bIQ+TnNJtakh3W41M6omXVbknbWr/Of25kd8YhNnLKybxSLsG8p0LmkRWezTNezFbN0
1ITY9ZAvUq/w2PSSOWPmmz6AWTqugtWi9dZ/l/jZ7NTm6K3wvtcgUNBgnQObXbyTZmBxZ8dm
F+/C4hQ2CGwrZrSfSLu6DTQU7cCmF+/Q7+/AphfvwJ/HDv3q0t2ZHdGeZUdIrXXUppVEwFm5
RaW7Vm6E3SQb13NqJK7s6mio3eHXl+4m2WgfhZ2HCSv4qFtVutMbYXcmRzxiE6U7doXVo7kT
jpApS47/b6ZMP6bpqDbR0iuPMCeFDzGXVCLvNhGzdGqJuDahHhnDb+fnTGH3TaW7jr7ADmx2
6U4YNZDbsdmlOxb0FbNjs0t3yqBB4IHNXd++VQWb/F/QbPVJ6FPwwK7Qd3RtVdHO7Ij2LDtC
/P0UViJGrOABk1+0YgyhlWtTlFk2RhQW0MNaGWiozqLC3eUYwuc0m/B3Ma5R9mVwhtEvWuEi
UvvVWebPO+3HMzau1HrVLv6nR94ZKu++OtZjlo3a62jW1VB9ULZbE0L3yzvtOZuYpDCz2iLi
FC7b/ZUdd/wV9oDgd7riJfsnG/EJ6JBxYHPf+eGsAL5UDmy64oSzgnds6vqybhUd4Tmwqd+f
VtdpYLvngU39fGwbow4yB3aJ5rxp0jqDLdqTsAFyta7CvTSKaCx0WHSJR+mdEd8cG/+hi4jV
qsOcFOiTuCYZr9vNnMfk2tDgYo3N9c0w1IhvReqja85ry8d2xlo8YhOjor4o3FptUSeFZdqK
s28q16Ejs3SMtHWWzmPsG45MI76rHcHnNB2lUYcNtt4GGpb1Piz+8434+sBu3R2afWw3OtjU
fWCzRV7soGGnFlmRe/dM5HVWcNpxx2aLPGXQBvLA5oq8vhnqRn5gFwiJOm4Ojs90i/YkccD1
WnhnDG2DpYGFRVqTPCKXOXkfk2x4K9pDELVIQUZ9+JaM49hldtnn9NJwIR4qRL0OcPwuLlqi
8W4cH89oi0dsQq2py7waf4S/eKjgf5XibsxaJulYZG1xsxHWj2Dy+iKNV+yX99rz1RGjKhFC
VGGHjFmbxLfG+3YjPopUI9CIb8dmy7sG/qZ2aLq4I7B5/gXNlXa2oQfGOzRX2Ok2GPVX3rHZ
wq4rGONyYJdU7268M86ohvYwRoNqKa7sxNUQoy4tK37n9y4tU2x4Y4qRxDIGdwN76OKiFcpO
btrvJ9eGy+iFijYrqJ/nGotEV3Y3ho9nUMMjNtHbR2YabQ+kBR/mXdERWO86AifpNLNO5KQi
SwM9AF/RFkSvPcv9rfZ8cfwW8y0RWWuM+hvNzuG8hd3v48JXVbEHy4HN7stiBTfoBzZX4Zlv
bQQs3+3YXI03/N0Glj8PbK7Ka1tp4MDxgU39fOJPONTH8AVdovGue/HtTGqwZ0kNFMlVbVQa
vaLz3dsKe5zbE9o5NuGnHt5Mps1fvAOOSluxNnfVu9m14UJx4Dx4EJyQvqp6d10mtjOo4RGb
EATUeyeptfQOvlmWWS1f14ln6TST2ljYwlQHtPVeZrV8vZ+YXp3uT1DWMqz4cwBu2nzHaPz7
Ux/JTny2jQaWJw5srrCjTQsejxbYXGEX/nrg4+vApq5v+BOi8wovaLZs7wVsADmw2WXjUtBh
8h27RNhdN+HbmdNgT7zzfWWbaR8UBquE7kM2XmFK/Epju3rbTrKx2szv1RpSCGazZNzDLmMa
PqfZKBtbZOs0IXD0qa6xWC56PVhkZ0rDIzYuAkSpKnMdWruivWprxnkvZ3E+pumo9m4j5nk7
G9glvGicl27aPKfplCJ9jOj8oIYfmr8zNBYIu+9y4uugnceBzX7DCqEnFjs2+2g2ptdgJz5d
EfDxzGuZUbuRFzR3dX3HAPZ87tDse6+DRbsdukTbXTe72xnRYE9s812m9bAQ8wd6tSaoky+v
OGa+8+CbZRPWe9267+Q6EXbvLLJqudV2k2wiaaJX6mGSCI5VLNJ2tV+7PdoZ0PCITai00cqg
COEa/q+pLss3s7yzdPz2rS68rcgoAzZZXjLLe+PUMs3mVUmNZGLYW/Rt1PJnOvCxYA/GHZpe
sBto3/eOzS7YaUMF3Y7NLthFyABasQtsdsnOHjig2BIHlIclO7Qge2C/umR3BjTYs4AGbs1f
TK7plA124FtUsrt5106yseq6IaJorApqf7moZMfXTVCzbFRIo4pSSx2Gslkj68ZNye6MZ3jE
poQX0JBKWlp4AqE5sSvMgJzOL2+1x3RUuYXXTCi7Vx71F44ewLPMn/OrM5r57q7aUHQz/a7Y
/dEGfIPAVrYDm/2CHYxmK+zY7IodM2rev2OzK3aEJga/oLmr27fKoH3hgc39fLpVtN75gi4R
d9fDi3ZmM9izbAZuIkX80a7h64CKuxWDpbfibpKNUVi6tGZ9DDhpYpH93k3z0yQb5R4Kwl+3
XTvKZpG4uzbdsTOZ4RGbqNmpRLxyl9YrWDdYVLMju87NmKWjpkVdCA2X9TxQrbqkaHeXjDZN
p7I20uZLNKjB6u6vrNp9iQEf+rZY86pYNuWRbsHHBZzxPLC5b33e0DzeQGbrTergpzuwqWvL
fWO0IHtgU78/rRvYAfhCpn42tq0M0FrxwC7Rm9cjlXZGRtgTG3/aWI0pju5KcaWGDg98tfXe
HBveaq8umweZMdocHBetKCZedjN+Tq+N04hT1SaE9svFvnCJ3LyeErczL+IRmfD9aP52KF2p
yAOD5BXFN9brMfFZOsZWdMgY2ir6FPWrVmwGLp33/hsAAP//7F3bruy4bvyiCCIpUtIPbCBr
fUWAvCYB8v8PIdv2BJgDa8oaLe299vTcznkoz3S13VaJIqv+/1F7fndin9bD/cd/P2BE+9t5
77s775ErNtCA98TurumogN5nJ3a3wmulwBXFwO5VeDUxaAp6QHfruwpa7xzQ3QqvNzCl6cQu
UXiDgcorNKI+sfJ3RRC9hdWFkTHaNxcXLVF4gy7AKTaScs29565cGoPdEHHRki7AwRHe7L3R
aGeUGjUrtDchrXjLucQbDIlfoRGP2ISI8E1s6bmFJzGsIRbs3IbeyrNsKoeNoLkENy7wgMcS
3717j/XP+Zvju0d/vfiWglTAEf63wvvGvnu1gqeJJ3b3YXFDx4tP7HZpJ6A0PrF7pZ2lDrvH
Hdi94k5T7WAzwIndK+9aogKaVJ3YJfJu0Hp/5TPUh9kZfm9Ns0aDFqzuFph/DM335shI8p+R
67tCTDUTuHNZYlfn/73BTOXkrWEz3zJXypYzbKvMK6w/Mv3lg/bjGZto6zMX9JWImCs8R7Bm
fndkzDJJx6r0xhFAx631rcYs930jn/N3x3LVbJK1d4bNBOc2rW959+u47/mmHlR5B3avyqsp
ZzQh7cDuVXk1ImfAI9oDu1vlKerScmL3qjxLvkkGPZYP7F6V15OrFPD7O7ArVJ4MOvGvhIb6
LKEhtxKLLpn1AkuJFSPx42PaKTbi+rNTY/GFKleQjawpSdYykHmT94aVoiRpYqWDbu1x0QqZ
Nxoav/IZHrGJmQ/rRFZyz65a4VHeFQebUgZVvEk6VjkmjCpJ979Q1bpE5o1MlqfvTuVs3Zr/
KitugP32WP77Mx+b7fdaygQOkJ3YvcqOUwNL/Ad0r64LQz15YL63wvTiwd2lnqyB1bsTu/fu
2oPQO9sfeseSYrlFGz8Du0TXDZrwr3yG+sQ0P8a0s2uGzN24gn22tOQAcGzRMsmmcvMXke9C
GjEou3dYtEyyUSm1ZmVRIkbtc+YOzP5F1w0aPa94hkdswls8Z2Iy5lwJHhddYRLBIncNax/T
dKLtrrwyxOLnA497LJleyYPT2dm74zsIjVOu0oqCP533MO83tt/ryR9ccJj3wO4+nzU0gfnE
7j6f9d8/7L7Xt3u19I6aUx/Y3XXZjobKntjtTx+hgz0Hdsnp7P04b7uyGdoTv/wwzm454m57
LwaPjC5RqyN9N8vG9Z3GEqUx/7pV37V6d6D5Oc1GOedGLu4segpRfbeiXW10PNuuZIZHbKIC
18yFEKkSt4qeZ645nh10AszS0ep6NXNuORQrLIiW1O36Xz5rz+lkJv+apPl+osNV1be+W6Dv
tpvwaQNTeE7s7sJdf2DD13+GDR+jU7MHdq+0y6lmbLt5QHcLOzLwlOPEbi/cCbjtObELxAMN
CnftymZoD3MzRFRZqGVCp1jiogVsLN8tTx/TbGrpXViq/1Uz7K284NkemvDNstHiqi6X2rOB
LairYjPofnynXcEMj8i4QgtzxFYtjjAbaP8Vp7grdN0gNmOWjoaxa1bfQ8TjBrsRr6jbZbq3
BJq+O519h6dWyJT1nYe2U9f9rLqdgs2vJ3bvAqupZHSu4sDurtsJOht2YvfKOw7rOlQd04pK
zTMTPjbchC+wu+t2raB1xQO75Fz23q2iXfEM7WF0hiq5+uyuIQg8CN9Rt5tkUyUrN22FegUX
qR11u0k2yrn10nKPoHnYY3lF3e515DB+0n48YxMVuJB3LNZdFYFydVHdbhSdMUtHQ6la5pJL
loaWIddkZ9yG1n3O08mvoRfz/43S3T/aho+/vQ3fI6ECapQFL8kFavhnmQN21D7mwO4udWZD
u9gO7HYtnNFjtAO7t0sxl2SoB/GB3fr9KfsyCKrNE7v18xVKxODzd2JXFDtvbUpco1ypFu1J
0oClM8K+RNs5+GL0i1acyY+mT+bYxCCJZfXlPPf8slLDpk/WmFLfdynOsWEXtlSYu2n4eoAv
u0Wn2DLol7gyLR6xoVSambbWyLiA+do0WU77MxsbFDun2ITdn5KaWFMRNBspL6mrM99uIz+n
6fgGkilrJaoVPfSY1fa/uhj+J5kEMuoIeWJ3q7wGBwUf2N0qrxN44H5iN6u8WN/BZsULvFfn
laQVPDQ+sXt1XkwQgR0fL+gKlaeDmucVb9GeRA5Y4s7UTH0l1AI+D3HRiprn7VTuxySbEGzm
oqi2Gqey8IzxklmUW/fkz0k2nKxHUgc36Qyez3OqC1x+xiLvyrZ4RCb0mhgbldqIwU7FVSLv
9qjgY5KNy7Vw+clxTE8En8/XJT4yt+0Gn9NsrGSXjhaZ4YxaqMdVb423RuNttgmUJA3rZjug
u7vF/CkE97QHdre0awXsTT6xe6UduR7PaAvUCd4r7Voq6Nzrid0r7SyRgDaBJ3aBgOA+KOFd
WRLticG/JctCvuTmqmj7SlyzQtvdeh5+TJKRcMGQYtpzrwaeZ8ukC8aftd1tlehzko3rNBd1
YY0UBr3gHAqvSZLIt82XfzxoP56xORpjW1X/M6M2w2saY5lvY9g+JtlEAzdx45yjjtcyepy9
RHnfJyB/TtNRlWhiyNKtKxjIOBvC8lZ3v45LYFXQhe/E7pZ5HS1Andi9Mq8mRVuVT+xmmccJ
9Q55Qbd+e0YpV3Ak5cTuPkWWDh6cndivPqW9wiTaE4d/SyWSMYyp+aJl2FJlSww+xhpvik3I
NW1UWtdaaoc13opxoUb3QR9zbDh1/5fmkN5KaM9iXPTVGu/KknjExuVaKT26+0wpE1rAW/G7
4WyDAt4Umwj66NyEangwoZvRZUEfgwreJB1jda3aRVwcKqMjKfYO+vjbGm+/R6AY2D92Yvfq
umijR108DuxeXacpek1gl0DHbr2/0qMnEXYvzktc7p4NG4uB78sTu/fzldQVnZY5sCuUXRsc
mF1BEu1ZkETpJeIKmKQK2HfDSw7MxsPGU2xi2Lia9Vx89cM9D5cMG7fbCtHnNBvtUlvV6O3r
uEvg1x5m/vGk/XjGJqeWI++sSI4BXXAT4VctcQnUOy30MU1HTV3SuejWagTuIla5yPz1s/ac
Dmm3XMSlKmWBh2umltW3tPsFXAKbv8VhgVd26ztOBO4vDujuw1ky0MHwxO5Wd9rRBLcDu/fu
hjkR2ld5YPd+PvOdLjh9dGKX1O0G1ZQrP6I9y48oJQIXyEwyVdBaaMkAqP9HBydmU2xcqFmt
/mOqJgKSoSXdUC7A7oZzP6fJWDGNfN6s/ic6OG1Loj1G4u4Kj3jEJmSaabznjLiDB81+0YpR
EbktQn5Ms9HWpUhRytkY3OblRcq7DrTdLJ3Sesm+fayV0XXrfTT7PR0CGW0UPbG7y3auJOGy
XWB3l+2042W7wO69v5Jgd9wTu/f+9iSEWgQd2N3CDu2CCuQSUTew473CI9oTQ39OtZcS/sLi
O3YCN0l+0YrD2NFaO8WGUnM6PVfJWdFRF79oyWFsGxzGTrJxHq6B/B+kr3P4bXY4ruoGBjJX
dMQjNjn1LL1rV/+dGpjFGBetaLjTwcjsJBvLLb+qXFq7wTEltqIAWWjQ2zlJR33f7qquFWG/
OV8bU/JWdb+AP2BLHY0ZPLG7a3YFPUF6QXfX7CSDNZ0Tu/fu9lQEdIE6sVu/P5FEhN3dA7r3
01FiNFPmxK4Qd7euYP/ukuYUEP2Jm7+kLBxTxq27ugP5+DUrtF2/13ZzZDjFYIhpGL2jm4I1
XNrtQfnnJBdKnXqvOVuMycJxKytCvZluQ8H+eMx+PGWT/V/KrhtysVZQNnmFFKLBWewcm8jU
tcpdrIe1JhzEu6QF0v7ySXvORrpyiYBAyiqwTv0t52TlK4wBwc6QFT1F39iAD92NH9C9UtMV
BoPDpyd2t9hkBZuXX9Ct95Zy5NaCR04Hduu3pxF1Cr7GT+xesVlTY9C26MQuqSTej3X0K82i
P4kY8F2O39qw/lD2/4dVEGIWZAGbkfneHJsY0qfci1qNgUrUloXWnA/fz1POseEkXJnCGtEl
DWNseM2w68iXpV9hFo/YUIxVc7MqvrMp6KtnyVg18yAheI7Na6yjWc4txlS4wKO7SyaR80Bw
TtJRUZOoWEukyKGCcy7W5lcXnP8s8z3QPO7E7tV4JfWKpskd2N0ar6Et5i/oZo1XUjV0svgE
71V5nKiBW4wTu1fl9VQyaA14YpeUFO97s/oVatGfBA34/oLYX+5Sc6aGTkv7RUtU3n166xwb
SS7xWHs3zgWdrY6Llqi8+4nKOTYh2MzX3ty51w6Ou/KacVei+/PifkVaPGITgi2HHuKoXIHt
24tUntw2z35Msgm9xkWrxWE+lYpOeCxReSODllk6qv6c9eJ/+M4CrGC/uwC/sf0eEWgvdmJ3
yzvtYE/Jid0u7xQ8tTqxmwVeT01ggXeA9wo8S6INdD85sLsFXhWwmfLELinjDYorV05Df5ah
oa4a1X/BLkEzWPiyJTkNvizeJ8rNsRFXN0JWtLXSewY7DpZIIhd494lyc2xcq2mV6Nak7os6
6s6yYtqe8+1B6x9P2o9nbChFlUiiLFn8JsHR1EsOwUfHxlNs4ti4UYTrlpatgTXWRefGnAcC
b5JOmF6rau7U6dVwCNGZ8zV6C7xfxYGPU20ZW2VP7F6d5yt7aeCL78Du1Xk1gek5L+RejUeU
Mty0eIL3aryaGM2uPLFbP1/hcP0DB2YO7AqNd1so8pX3SmnozxI0fNVlK68sV/8WQY23YuV1
jTco4k2xkcRarffoDuSGGvAtCXSuI4k3RSZ8G02ia7NkIbCuwktO0YcGfP1KaXjEJrz0XEA4
Fa49C1rDW1ORHMSkzbFxsdYp+yZFOndjRYtetmKSV/r9zMcsHc2xjXdlLzH0AdfwfsvM4N/d
gC+j4QAv6F5Rxymm/dFZj8DuFXVhqQfKkhO79e5KS01BXXdid4v2DjrSH9DdpeNsFdxSHNgF
ykHkLmDV19ornqE/i2cojcxXpiaRGItmby0xIrY8KKdMsaFUqcUBYPFNCPru8otWSNRa7sNv
Z9moVFHNzkRVsXtDkz1RD/xZ+pXO8IhNmO91qbkUbr0xeNC8ynxv1IA3SUctFw0TbymUDdZB
K8qq1Ac7iFk6maRVvzu+f0Br3nHVW9b9fVn3k0Z5LYOxGSd29wpbCqifTuzuw1n09CGQe7Vd
x0MfTuzee+vbBdQ15AXd3vVJ6GTPgV2i7Qa9UFcsQ38Wy1BEqPs2vTMpWGGOixaw0dGh7BSb
l6+JEpuFTzSa+rekFYpau4+8nWWj0uLsr1uhqmB5fYO2u1IZHrEJleb3JhfqvtPJYGbdIm33
ytgdP2qP6fjjW8LewPxvV/aoGFpxKiu3dD7n6RBrYWkll6zw3XmX7BZou+3me0JoWPuB3V60
Q83jTuzuop1v68Cz2AO7W9i1znC/WGD33t+aCmgke0C393sa6gJyYFecxOpgaPZKZejPEjPU
JIp2ZJVVUVuTFaUHslsXsY9JNuGpTJKrL07aW0U7upYUVFu/d7qdZaM15ktfR7EdbetYIx1e
Z6XjJ+3HMzbhj6xVNGpcJbu+Q4XdkjHTOijaTdLRMGmxYpXyk6LdkvGQ0VnsLJ3clGv3t0Bt
aJPOW9h9Y/+9yMEC5d0Lur1wUsCy04ndXbITBqcBTuzeu0upo+ruxO4u23X0+zuxu4+M2dA6
14Fdou8G0xRXMEN/lpmhlaqyf39igg4oLVmlXN/dJ5DOsYn8CzIjK6UWtGNjVWjGbRnyc5qN
+ZrbpFGNXGC0cLfEwXeo765chkdsXKn5/kHC+7q7vMN+On7RikPMUWjGLBttXRuFgUgjtOd2
UWjG0BRllo5olGiYciM0rOh3NUX5Ehc+QocXV8wtfmMfPt+7wEZ8gd277EsyBhMzTuxu2ckG
jp+c2K33N/z1WkPPoE7w1m8wHPYI1EEnduvnk5qkVtiNL7ArhOfIje/KjuhPDP19z9PU/O/I
4i3gExEWfgvYDN34pthIctlZOmuu2fXaTjO+eps89zlJhhP3qlmN41AfNPbkJGtGPAY7nCs5
4hGbcFzRxrnXFk7DqEvLGrfkv3zOHpIJvxVqrF1Ns+HHxUtcWsQGrQmTdMKkpfXSJVtRuFFz
zkH2V5ed/yQvvqzYL/GA7tV4muDd9ondrfEa6mR4YjdrvJIKgRLlAu/VeJwyarj8gu5VeM1X
H1DgvaBLCou3mQuazwSJ+D9P9B31Ho6xzK1n0APXdyRr3JZvR3gn2YSlnkgtzZdcamBb0yIf
vppvO/An2bjAa6VTJhdE3cBfaly0QEQMfPguNj+esXGxZl1f0+LRgbrThi/bbT/gJJmQahIx
GzW31mpBC3FrBN5t0fdzmo4W0pb9F+mvAmH42Pi3rCv+A2z4OPn7BLThO7C7j42bgjbGJ3a7
thO04fzAbtZ23b8U0Cb4Au/Vdpo6+p45sbvVnaLTvCd2Sf3utqyimS4N8SxNw5fc2rXUqHmB
9ls2uXPHLVom2UgSVw9Se3sFjILjTGsMZ1odrLpTbKKAF7OifncI9cyMa1YoonsXvovMj2dk
wlCv1VbNugtvsAOV1kSDDFz4Jtm8wts08icq15hS3unCR+22LXCaTjFTYgnL9Z7ByneeVN9v
fferuPBpYvCU9oDuFXk1ZdAi8IDulXg1qYLtLyd2r8Sj6NpFz5BP8F6JZ8kKWLU4sVs/X8m+
ZIEP4IldUsK7HbXUzJeMeBil0bVm7dZaBs3EbMkxILmsvF94p8hIYjZXRa1xlFbQI1peoVcH
R7STbEKtme9OzYpoBtu1Vh3R1rt65B8P2o9nbCKh2roLcJIsGYwapDVsWP/ySXvIxsWav3LK
OQGr4F4vrloi8W5HeqfplCqkytV8qVRwYvEt8b6nCx938Aaf2L3CjlMz8ODuxO6VdpoM9RB9
QbfeXWnJf8LwwWJg995dS2ENB9vwtc2VRY5oYHQk5cAu0A4it513muXSDs9CGkpttXSK/iQF
bZkW+fANvFom2YSlnvpPqZPLIAWtohd5tQx8+KbZaBjeunLo7PIO9SNeUVUdebVcbH48YxM+
fGyltDj1VQErBnHVCmF3W+z6mKaj2mrtLupKoQL+clb58LW798DnNJ0STt5WjaiTgQ5jbx++
b+3D1wj0uTuxu09nDZ09OrG7T2cJHZo9sXsVXk9Swft7Yvfe35aooOdRB3b781dQn+8Du0Th
Dc5my6UinmU0RKZYbea/ENePmCZa5MZnNGiJmmITYs0lkcTKmwvYXOIXLYlIu611fU6zUWZy
WdT8D4aPM1f8UscKr1wa4llEQ8tm5BIi99wyaHj09W5803R8g6Ixbh2GOhWms8RS53XmMn7W
ntPJpeccdVX/8YC9kW+F9z3d+ApomXRAdxfuuqHmYQd2d+FOOzpScWB3C7si4NvoxO4+cRd0
ZuHE7hZ2DI/0HNglwu7WQ0OzXuLhWYSGcpcurw4icJaR1/Tc2W3f/sckGZdoEZ5BlQv5CgWb
8S2YBqN2b5A2zUZVehNfcal0Q1Xqitm2sa7TSzk8TNCgsOHrJCFUwVfjqgSNcie6P6bpqJXw
48tazAo43r+ocsej/s5ZOi7qmlRupt1AF9S3rvvGZnxhcYZX7gK7d4HVVDJ6dndgd1fuGBZ4
B3bv/X25n8ItY4HdXbmTArbFn9jtz19B7fgO7AIVwfmur8vXXbtUxLMcDV8JWhhVmL/ewfM/
nnRZ/ReFN5iqmGITlbuYL61RRyP8bHaF+K7lTq9+TrNRI19wS20ioAcUrZEQAze+i8yPZ2TC
N7lEkJGUas4JPctc4rYsOhB4k3S0dsk57Jaz62/sUVsVo2F3UyKf83Q4IhJbV2lC4IstT1aJ
f7bA2yff/vc//vs//+e//o2y/7F1fcLeFrs1ESiHFryNFwjvn2FHqCURg96eJ3Z3S5oqWGs4
sbtltxTQRPzEbr2/LgXJ0O/vwG79/kzjnmHf34nd+/kksjzBz3dgF7xMiAYzpvWSdg+TNMSX
Wleq0sJWDdV2K4SqykAMTbEpKUc+GnUlQnOW45oVqvs+5GSSTFiAFuu1ikpuDXXeWeG7ynnk
VVMvYfcsRqOETaT/lV2uKly5WzEDyLnd3ZyPSTqU2H+NuRTLJRsYChIXLWFz60Y4zYaqRPaM
/3Jyq6iT0JyL588W3b9WVfUnmhHqKx0E1niB3V3aUjjp5MDu1nhdwdLgid2r8SzlCg7hndjd
GkoU9Pk6sVs/Xy1h0gpash/YFWfnt9kgvvS2S0g8S9NQadzErLTSwWaFVRpPByvvFBtJ1eUq
VSqdemF0nHlRU+RA5E2xKUkiKU2yVGsETviVVJaMM4+sL9ulI56FaZRajEtrLSKKwbVldmL2
z6fNMmiKnKLjCiekd209TiQKLIvWdDYMSquTbERDgjfprsBRxTq35r813s/2I6w9zEGxtesF
3S3tzNB5gwO7W9r5Nggu3wV2t7TDJ3Jt0UTuE2nXU8Nely/kXlknyRpYWjyxS0p3gxPzfkmH
Z/EO6mLOcgyIREwx+EK3JS41PDgxn2JTEkkrVEvupaC7Pr/oy2XdJBtX272qCzutGfwp+EVL
rJnzYAPRL+XwLKxCpIvW0l5yCDR68KsW3JxBB8DHNJ1wVcy1uALOorAT4ZrKqgy6MybpdK4s
Lre1sTI6zNzfSSKrhN1PMSKklNHBgxO7V+FZMgFX2RO7V+HV5G9m3IywrijuPFF4NVU0Lu7E
7lV4LZUOmjme2L19J5rYwMGhE7tC5d3GIvy70pVYQc8yHiJr1dfeXno2dAR/SXsX6a2S+Jhk
I6m5ZlV/G5m5LEKLd32FZq3tfhphjk3Y5HPzJ0dby2CzTFyzgEzv9we0dAVWPCITco393piL
CXK1hw6+fLnIm6XTil/Ri4o06x3VrCvuDufbNs/PSToRBsb++2/FVPHqXZ5i8xZ5P9OK0FI2
sMn6xO4VduwbIdCL4sTuFXaafJkEfyAHduv9pZYEtSI6sVu/P9FU4RS2A7v380ly6YDd3xO7
pHx3X1ShK6qCnqU7UA0fwtp8wTXY8G5Jcq7RvRnhHJvISKtWXdxJa6h9yJrkDWr9vh9qlo1r
31pK68Ja0emqNQd/1O9tL+mKqnjEJtLinQR1p5Tb69QXO5VdE2s82ENM0qlVey2vLk9r4CGX
X7Um2Pgvn7XndDhC/LhKLRXtWp3NvXtLu1/AjLCmzKAd8Yndq/B8j2roS+/A7j6chVM6XtC9
+q4nKqi72YHdre9UwQyRE7v387WEns4e0CXqblC2u2Iq6FmwAzVuRlVYDEx3j2uWiLtBLWWK
jCubbrVVifUJz9xYkmjc+r3T9Cybkokpd5ZMvWHygRepIb53vKQrpOIRm5Bp1Z+1UkrvvqOA
5ypWTCKQ3rcBzNJxpRqjFZYl+24C9atZ0bo8qEJ+TtNpbNpc1ZnvjzLYQjg7bP4Wdz/Th9CS
cAX7Vg7sXlUnKRP4+U7s7rqd1gdOhHWzUQ2FLTO49p3Y3brOOq7rAru9btdBJ8ITu0A+yEjZ
XUEV9Cyogqz0WqsLLa7gWGZctETa3aeyzrGJEhwXtqzsfxhWfFhWt7tvhZpl4/eGJGfunRWW
divuDefb4L4/nrQfz9hE3Y60NleNlCNqGj2RXRJnPKrbTdKpNWuh5qxq9t8PKu1WNEXK7XDI
5zwdX8KdjRBbE3AQ6V23+8ZWhJZ6Qa0ID+xehaeJBLeCC+zuup3AlbEDu7tyx2gE5wu6vW5n
aGHswG79fCUnA9sCDuhXn8peIRX0LKSCfGVqEoZG/m9Hve6WFO70ls3HJBuXNjVMFaOaoh11
sVzDpt2eY35OsylNXeBJK1VKh+P7lsghHqi7K6LiEZso3PXW2O9NqVa21u2G4m6STdVq1DXG
cM3A/pEddbtJOs1inr+6sONGYL9dDJb8juJOYHH3pIEc+05XdGd9YxO+3MH33IndfVAcgU7o
QXFgtwtOwb2vA7v1/vp3Uhls9TyxW7+/ygk1gzqgewWnhXcGvB0L7BLJORACV34GPczPoBK5
W7m6HkDHeBcZX9878M2RKamYr8cunWP7C3bdlyUub5HFdi8Dptj4Q10iWzliZwq69Y+LVoga
undnoSs84xEbF49aKftbuDNnNEVnlQXfrZ/JxyQdStGPwFp8RyAMhviGCcpXK87Jm9NCQEth
4poVjK4Mnfo7Ks5/lAdfB+0jT+z2mmJBx1AP7G6J19BTxRO7V+LFaCnus8zbfZZ7ChMR1Kol
sFs/n7I/86BF5Qu65Mx4MFt5BWjQswCN0jVmEXN+2b2hGu+rrVrm2ITrSgg8X6eitIgtvKus
WnjQfz/FRuIgpFsXLqIFPJWUJWzGGu/Kz3jEJjSeP2eVnZF2Ag/0V2m828zoj0k6lGI4Knd/
b+fMcFIirzgypjzYTkzenG5SqQgbF9fhaDfg3FvtrfF+AQ8+Q+t3J3a3uIvDFFScBHa7uBPw
+zuxe8Xda/waFHcHdm/9ribfGYPP34HdK+5c4lSwqnJil1Tw7kM06EpqoIchGqVls0KRtQr+
oNYk4B6JX3dr7hSbkrRzdJ4ZR9ELdeLTFS2BtQ/qKlNsJIVrRtYmJWcDreviohUKog42EldQ
wyM2OfrGc2Phri7v4PA6WRFedy+IPqbp9JolhxMQseJ6aIlNog26TyfZmO8fWKJ9xFoFqzp+
1dukZZW8+ylOfDHkA770T+xelWeJFR38OLB7VV5NSmgJ78DuVnmNwRLZid2r8iKeDexUO7F7
VV5LpYHP34ldUsQbtAZeUQ30NEaDMnP1J5AzHJKkC5Ze0tu85Y9JNiVxz2zkYiLnrKhD8ZrB
D7n3W55jI65wWhHjUhsZXMRb412XBzO9V1LDIzb51YpSzGUeW2mwd90SlXdvUPwxTadz7znc
iallhp0F5xyK/0TnPqn8c5pOjRzn7tsjf1Vl8M0WV71l3t8e/NjuxUcFjJF8QfcKO3+BVYEz
cAO7V9hpUvDs7oBuvbfUUq5omP2B3frtSU2iYOPxid29rVAFZfuJXVG8s8Fie0U10LMYDdJI
EjNT7q2iR0xr5nl5IOum2HCSXsJponbXdmBAMS8ZGaXW7+7N5/S9qZl9ofUb47oBttGpS6xa
RvO8V1DDIzaveV6Xp9JaCzdv1Lju6+d5J+m07M+a9CrZiRnsbbJigkV0UCiepBNOjyT+CqA4
pkWz6+aGFN+y7hfw4bNUwG38Ad27vpZUwIaHA7r7aJYzGOB2Yneru6rgWv6C7tV2ricF7Ao8
sXufve7vdtTn7cB+sbbjK6CBn7nmk9ZSK+UmtcDhGYu03f1p2Rwbl2nFOrdSem0G2vjykoZ3
aoOD2dl703yt9fviSovEsH53WjJbQb3ftwDwlc/wiE1M8zoJ32MXf84KWDTY4LE8S6dRK+qq
u0uXQiidFQ0uLO0+PWOWjhVi/9lojdYG0CMjrnpru7+t7bbb8JHgNnyB3V20i14htGgX2O1F
uyoPbPhku7BjeCU/sNvLdmBN9oDuLtpVQcd5DuwSYXffB8VXQAM/Dc9w0VAq114ymqayKDxj
ULSbYxP1N9eoHF6xhUGftzWOxC7s7nPmZ+9NdSXfc1PWphUVdivsKF1K3kmHP560H8/YRPlN
/fZw3BvN4J5yh7CbpBNmxKWJ0/F/PTxluqZmN9B1k2xc0IUZUAs72FrQo9h3zW6FrvtZ2Rng
OcAB3V2zM9RC7sTurtoJuLwc0N3SrhX8RDawu6VdF7DmeWL3fr6cakeT0Q7sV1ftroAGfpid
ocauiLRbE3hadlHVbrDiTrHhaNlnC21XXT9gvVy8pJfLxd1gxZ28N611USuNqFfQtc4vWnG+
3G9rkH88aT+esQmZljvXkiVrq2AT7Q5xN0mnZeuFq2UlZ7RV3N0el39OszFVyhKxddzBwCe/
6Lcclv0SCz7Y33RFx/i3NuEDfXdP7O6Com994IJiYLdrTgVnoU7s1vvrOlzRvOATu/X7q5qK
CXZ/T+zWz1dcq6Czbid2heqk+5RUvrIj+FmuR+m9a6X+iluAffhWFOFGQ7xzbHxzSepfkrK6
HCDQJTEtsUhsA3O0OTactLugoazZaoHzeFd0dfBrNmb8pP14xiY8WkQaafF/gok9cc0SzTmo
XU+RoWg4jX4EYpHCaIvmF/c0fk7fmnB81uLbgmIk8OTNXLbwry46/0kufA3slT6g2zsBCVxh
T+xuhdfQr+/E7lV4msLJHbW5CexehSe+acVu7wHdq+/8jhW8oSKwS/TdoKp4pUfws2SP0kqn
+JukwckeZUmyx23l6mOSTUlioi6GpEgYz4D6bsXeYOizPMeGU43aqDVzLmgyGE+uug88+PgK
j3jE5uWzLLnFCbg8ODH+apvlOTZhsyytEFNh10Voq8Wa0erRTmLy3jT1LXLOopkNTktub4uW
Rfpu79LfoucHq4Mf0N3CTtFexRO7XdihOUsndq+wC7cacETmBd367bWX7wH27Z3YvcJOfQFF
K0MHdoF4kNsFypfbK6SBH+ZnqKvOCMdtgh6w+kUrpJDetqp/TLLx7WUWKq8+dang/HdctOKA
deCVMcfGNRpV34+SqWkFa128qhdwUCK+MhoesQn3PSnNuGsu5HzQAd4VdEbue7N0erde4xyf
uKNnXJTyitNvue3U/Jymoya9kbpSzUXAyc48+SJ4a7tfxX7PH0gFz8dO7F6Rp2FiACdABHav
yKtJCzjreWJ3izzNaNjngd1bvetJCawuntitn0/9DafgwMyJXVK/G/RqXTkN/CwKQCOQt3bz
BZhw+72vzkmbYxO7OXG1yrkVbmAfflljJlhHVZUpNpzay0bQ/9GLENrjuKJ/d2iyzFdMwyM2
h8myVtNcJWZGfxWT5Vk6LoriSSuvXBDYr66vuDs8knmTdIzFukSWXUwZoTJvrrXhLfN+sv2e
gJvGE7tX2kW4OKhMXtC9wk6ToSYjJ9Y/1v8BAAD//+xdUZbtpq6cEQtJSMAE+qN7/vN50rbd
Hy/LpMyl6ZNk5ybn5qPIsjbYFEKq2je7TiYrodfGB3br7yc1+X4Gt3sEdvfBIqN1ny/okuzd
oL/y8mfgZ94Z5Lut5KKt5QpLvK1o7CLju9Kuz8lo/C0np6i1ZMvUQbcJH7Sk7K7e5bu+pufG
ctRrlhDRMbQzywetyEXeigl+r7SPZ9E4QWvSWq+ta8MlTVboG4x7PSajaZG4M2FqJWc4F7lE
oSXXQeHdZDhaxM/uoj0Xxn3r5vQJ3qzuj1Dfsw7mTU7s3u1VUi24unJgd1/OEqpkdGL30ruW
FO2oO7F76V1L1kB56hO7d/3VxA015zuwS/J2A4J3WTPwM9sMKlabE6Kaa4M7RmmFap3xXW7o
czIaTi/1XidEvRij3n9r9JX7wJB0dm4sijas1szykl3DCN6SvN1tz8v3Svt4Fk1ItdTK4qGw
k1bwLLGsm3dQ4jkZTuOmlIlZxf9G6wjbEtuMeq/lPRuOhkMLadUenilod/Jbq2UBw9uuwYfW
4RzQ3Vk7gxs+D+zuvJ2+VLlABb62IlH/LG/XtcAXxoHdnberqMLiid2etzO0h/HAriB2t6p1
vt1e5gz81DiDaqaqUgnNRC4jdoOG2aloIgknhWoLjdgMelStyty1AbGbnBun2y3k8JpPUEez
qrZCCWRknMGXNcOjaCIJ15s0P0aEJhDcMruoyXSQJJ4Mp0Ujbu5CJTQF0XB+PnU3GY6Wwtx7
9a2oF0Z56jt1t4LY/ZIIX0E/+Cd27w5bnFSi1lQHdnfqTtBO+Rd0L7/rCTWOOqC703bVCLyV
PbC703bVwHu/F3TFrSzdS1TIZc4gD40zzLkDda5Bijabot2lHj4nownVmWJVapWwN8UyDzFo
BbcbmKLNzo2T7pCZerVkolLtS0zRhhJ8clkzPIom0m9RLernk2Jk4Ll3gwTfbDiNqnG4opEU
AysAFnG7UdJuNpyQ8M61Vmu+3OBSyLlWuz+d2/FPiPChZgG7bxdBerLgo7KAB/+WMKAwxjJP
7O4LbAV37gO6nwODvOIF3XvC8Q2mgHvRid3665mGYgb2fCd27/P5wQDsuz+gKzKcA6E2uZws
5JkvR4iRVFX/s0tHeeMayZjbSsvPyWj8E8SNNARwwmoEFNH379aCaOpAiHo2GpbsBK4Lmaqg
fdIrztJMg9pEuYwsHkWTU42+4tDUNqUKfrZ91BJRwHYvCjgXDqXo0JLoKZaeQb8hH7Qmwfm3
S+15NLVFMGytv+QgsWjeF9ereN0vaQJWxj75B3T3JaKfy2BNu8Dupnc9g5fsJ3YvwZPUUFXl
E7uXQIXQH+g1cmK3Pl+TlMEi7QO6Is1Z7q+w5XKzkGfeHNqdu5vTY2Oc4K0QEiLVwa47FY0k
Jw+t5FB9Rtm3j1mR5aztvqV4LpiSeoiSkHJvobkC8ru+5Ab7Ni34vdA+nkUTzhwUStzSqOeu
sDXHiiwnD26w58KJTL/TOyWtll9G19uuBzjzvWHhbDRBuVvzT0FluGMy6buheBG/29uYULtv
59gkH9DdxM4qWBJyYncTu1ZxYhfYvcQuzvjgpdiJ3fr71ZwKgTn/E7v3+VoqqCbliV1C7e5F
eOWyjJBnlhG+L2X/ovvJrBGoEsFrDDB0UJ04F01JVDnEb/yfrKDASlnjd9zzfcXYbDSh8qxm
ktUI/Nj5oBXJLhrdYF+eEY+iCc0kabV2cQKhipvQrjH0uG87mQ0nBPqb9uxU1Wke2om7Rsxn
0OI0G05v0U9cufm/FPCMN6t+82Z3f4oqYMYvyE7sXppnyRrq6XFg99K8mrSiNf0Hdi/NC+oB
qtqd2N0XoEVBmnxi9+bv/DepoKLHiV1xRXurBuab7+UcIQ+dI3z39c2qi3RCxcDTEjGc163j
3d47FY2krlTCGKw27qD7VAxaUah4myX6moxGUxZxfte1l8zgYtMlF85O8+5lxuVyjngUTRS1
eSTcS5XOoFhyXiKGM2Z5k9E4w2tmzlipNNQjwUctSeG1v11qD8Oh5KtMjCvnzAzu+5RoanLe
JO83NQE1taywa0Fg9xI7jstCWBQwsHuJnSaDX5ADu3V+oxSRwe7dE7v19xNfU2Dt1AHd/XQd
PVac2BW07lZHzzfbyzdCHnp6+ItbSISsCCizskzs+d5Cay4aTtxZtRhTtJOiJHVFzSv1PNhr
J6ORzNap5pCea3A3zQoiRLelat8r7eNZNE7rSEonj6c7EULbT1astHH7yWQ00fVduUbHhjD4
oZr1r4XD+fofwvHjXe45RAErWAXgo/6V7Sf/FVVA1Ov2xO6ld8UpG+hP+YLuvpxl9D7lxO4l
d+rbANgc+4LuJk8G3g8c0K1PVzgVA5nQiV1xMTuwa5PLK0Ie+nj4W1urf9apowZni+zaXoaf
dxvuVDTO0jLn7C86+T9o47cPWlJ0d5d//JqOxqi3UrirmnWUqK64NB8Ik3yvtI9n0YTECHdR
J6lCD9jDnDDJE243GU41rb07w2tNK5hjyEsKPKNt/u/W2uNwOsVfrYqzbwYFsfJkheeb2/2u
HiB6FDmgeymdpMygnt2J3Z2x89ce9vEI7O6MHRlY9XJi92fswN/vxO59Pku5g5vTiV2Rs6NB
D+PlFiHP3CJKs1ZDAqy0WtCcXVmR5bLbovDPyWgi/Ra+WTlL9v9D6wdXZLmo3uZTv6ajEap+
2uMeQs+gMjIvMq697f39Xmkfz6Jxipb94B93l60bg0stRv00sZsMx09DJLVTE/XpgbNcP560
mw2nveSJmp8hlEC5pdlw3sTuj9AD5Ao2K57YvQxPEymo5nFid6ftBLWQPbG703bhnIT+foHd
zfCq4beegd2dumMDrUZO7AqGZ4Nb2csuQp7ZRWiTUoWNwyEVtuBdoofCg213KhpO1EnVP0Ya
fX9gUt8HLSm2G/TLTkajPUvUumv4taHRrGhl5lwHt7KXWcSjaCIJZ5G9I2FW1EhvWU/F3y61
x+FUteKBRCqyMSyRvKJMdZy6mwyn9ZJbdM1LzgyrArZ/5bWs/IQqIFo6vqJ8Z1mnx2b9PUmt
MHb2O7G7r4qpoJVsB3Y76xTUx+PAbp1faSmDHR4HdOuvVzl19PFO7F7O2VMv6JnswC74lHC5
22ucCVxOFvLMl8OpZo8G4cgngBZlPmiJP/CtGd7nZDQlFd8yWSo7EyC0jNkHrcgq3na+fk1G
I+HdZJ1rbZargVWxacV3jokGHeOXj8WjaJxuZePScw41atwguK4pBRwksKfCoSRaci5NiQlN
Ksagn6ack5Pjy8w0DjfW/XOAMug+9R340ynnf0mEr4FGHgd0d14xdzwvFtjdDK+BZkkHdC+/
66kJaBB8Yrf+euasKBfsu3litz6fRiYdLPY8sSsKAst9mVa5/CzKQ3cOy61Rl6JmBPcTLGnh
HSi1zEUTBzlhIWndOR6sbbKkD6fn+213LhpJ0ot0ydUZa20YJZI1xmuc77OK5XKzeBRNDplW
E+dDpmwCZuR91IqO5Htd4s/JcEKXWEqpOVvX1lBnbV5SD6j3Ksuz0WR/cVpwcJEGVjfGoDfB
W0Pw9gp4tJCDBN/AE7ub2xWwZvGAbmd2YMXsAd1bD5CTgnccB3Rv5q6mImDq5cTu5XWaFPXB
OrFLeN39bXG5HBrKQ/eMXAprZakV1ZrhJcZe9NL5uttsp6IpSbt0jsKz5uwBY0JljVR0kzsm
9DUZjSTuYYiXzTp10G5C1vTw8q3G2/dK+3gWTU6ld6d1qlmJ0MlZVA8ot/KIn9PhdJXe2SKx
ikpX5iUqQEx6byE3G421Yv59iT7rOBahwjnvcsBVxO6XBPiYwa6AE7uX30X7K5hreEH38rua
VNG72QO7l+FRMrQi8MTu5XhOyQuYWzyxe3OL4jwHrA04sUs43v3tbLlcGsozAw0JazQuxp0M
7ytYoUust/mhz8loirOiqtqtUMsVLDora3o+2mjjnYpGQh1Bm9OtWpxPgA1QaYVkAVMbZIkv
k4ZH0YTkSs++ylgkd8KFWpb0Jg+UHmfD6SWHSXDT1kXBQo0Y9aMFjl/T4dSYnBz5yObv0Fuo
ZadQy96t31Iu4PH3Bd1L63yzRIsdTuxeYqf+gQXLxk7s1tllJ2sK7hUnduvvJzWxgYaSJ3bv
+mspFEix3+/ALiF2d+ku324vi4byRDafkrSQzK8qoQ+LFg+t6eUdbLZTwTjhfHUmt/DxJJDX
8Zpoer6bmq/pqanBGApVVkZlQGhyq/0Lr7uXAyqXP8OjaHIq9bj401yMYGe0skbVZJC7mwyn
5bCK7lVCxhv0mfJRK1g32yBPPBmO5ThBSNPKhFbb58lDxJvX/RkCfBX1zzqwezdYP28beHt3
YnffzNKDojvaXXXHnKyDmbETu5fgOSmqDBK8A7v3+Sj6r8HnO7BLCN69Wku5zBnKM8X8ksn5
Xe1aW2e0eGjJ7azxoBRqKhona8o5+8su/kXC1VpWGGf0PMjcTc5NF2dFVDqrVLAzmSZr3f9y
OzvI3F3eDI+iyaELRL13M62m4N6SlwgDjRneZDiNNBpEwvWNQEFOH7QiD3nvgP01HY3V3Fvx
j0CuZPDk2BT9fhO831XhKySwtHJgt6fuOuhMcWJ3p+4UrVg8sbtTdw0VsD+x21N3HVx/J3bv
+qupK6gldmJXMLtbtwnfby9/hvLMO6NkLb4zae6aQXEGH7TEO4MHd7JT0UQaTqN35fx7ZxXh
MHc3OTfOt4uz+bgzb+Bu6+/qGu+Mv11pH8+iiSwclUhzlVDQgWVNfj53NxlOy+JvTGZmNQWl
yfOa2Sk0uJOdDMdyeEb7a+MEXME7u1nHuje1+wN0+MzPJmBV0Yndnbvz1wpWRAns7tydZFB5
58TuZXiSCNUpe0F38zs/4YOCLQd27/NF3RmoUfGCLmF399q35bJoKM/sM5zaKXNtYeAJ0mkf
tIKrKg1uZqeiCcHksCH1N6lpBQ1vQ8x4Cbu710OZnZvuU9MLUbVSwQ+dD1rTLTvo37kMGh5F
Exm4QiUzGTmDAN1AduTtJsNpuZg09u9Opw5aRS9id2R3PS9f0+F4FFoLxS6kBju92b+y4u5H
NPgIvCajFVdk/1gVvpJyA/s8TuzurCK1ChcEBnY75wSlpg7o1tkVTcqgBsqJ3frrVfMVhfZ5
HNitz1dKUgGVvU/sktviO2bjXODyjyjP/CMobopFuXEXsF/UB62IZtjLOxWNHy19zwzTtrjB
AxvVfcyCYOqICExOTZXsC8eqdKcB4JdujaYJ3wrOfC+0j2fROEFRa2JxnV+pF1RaeMXkOOm8
m5zPyXAiF2+1cFbNlOFazRW5+HCa/rul9nhyGktp1nsp+VAM+MG77z+dc/53RPg0+eKFBSkC
u70kUA1OKwZ2N8VroE36Ad1L8QxvRT2xeymeJLjM5sRufT7NSdCX4wVdQfB4IKFx2UeUh2YY
qs7w/Hwm/nVHC+hoiQjfrTDx52Q0JdqSGxMVyWwgJypr2pIbDS6NJ+emV5+TzqRcO6gH4oNW
2IPx7RX490r7eBZNcDUKDV99ifF1OHG1huHdyyzPhUNJCvk3W7tILaAucQxaEs1A73FycjoV
JRJh4UxwzvdtyruK4W1W4cuJDdTxOLHbb4zhdsoDu53agQaHB3RvPYBvAh28kT2xW3+9Rik3
UCL3xO7N3rXEaC/PiV2SvRvUaV0+DeWZh4YqFw51NOcR4Nu0xEuL7Fa67nMymOIUPyRAtNVC
BTz2lSUNllQHtm2zU9PMnDyE07CwoeLXbUUFHd82rnwvtI9n0eSk0ZmsQR44v0raMJGWFWyI
bnUFPyfDochlUG4elJ+4cEniFdm7YT3g5ORYJjX/SPVcfbGh5Y3vesBl3O5XhPii+KeBQnwH
di/F01QZJAEndi/Fq0kzKMd7YveSvKDl4LfpxO7N3/VEsNzygd2bv5PUwdfjgC7gEaz392Z6
GTXoMxMN7t3ZkDYneDWj9q9LpOtGNmlz0ZQQeystn3+iJhorVs7QJm0uGvGTi4Q0WtRsErjW
YtAPlwXq5dPwKJpXWWAI+nYPpSlY+rOoLHDE8WbDCRE+qU08lJYrqj/T1zDw+1zxbDhm3I1r
70wdFXqYza6+Sd4vC/F1NDtxYPcSO07+fQCJ3YHdS+w0LNPBQ92B3Tq/TIkKaptwYLf+flJD
9BPu5w3s7oNF66iU4YFdkb27LVz3DffyatAnAvrhyWm+OZXuS5BgpZYl/mg28Eebi4bDK8dZ
NPfauIEZIl7Tv9LzXWb1a3puzIhLqyJUG6hLSYvuMgcOuHpZNTyKxkmattpqbsXCjw+9ml1R
9Dvs+JgNp4W3SSNTI0WTq6ukWgZ3s7PheBhNWusWCoOwycmb2S1gdr/UztsreL46sXs3WEnW
wOPsid19OUtgeckB3UvvQqQCVIA4sXvpXUtgK/QLuXflNac3oC/0iV1SdXdfC6WXRYM+kc0P
lWXR0orvt9rB3EMMWkLt7pt556J5ySyz/4fNuME9IotUlu/tSGenpip1LT477OwBreuqK0y4
+LYz+XuhfTyLJjRXnDWYVHGWah1WWV6Rg7xvRPicDqcxa9WacwsFUDTLtYbZtfsWntlwLIvT
bc5GFVaPfd/M/jNF+LKB7agndnfSTjsq0XJgdyftLD/wz8j7/TMaat56Yncn7Rrc7XFg964/
J+Jopc2JXVJyd18JpZdJgz4zaSiZ/OW14psuej2/TF55kLSbiibyb1zJaVCX0uAOhCVJuzrQ
vJ2dG6shWUcSVvNoPnVO8fb/UyEd5Owuh4ZHwQSzK1XC2STqd+F2ikUafANmNxlO8x+p+BsT
7K42tP93kbzyfcfsbDhq1opyKY0KwR2z+pZXXsDsfiVpVxM1kKCc2L0bbElZwX7FE7s7aScE
duyd2N1pu4qq0L6gu5N2OL1rv0DvesqtgceLA7uE3g0Sd5dDgz5zaPDzerThUjYh0OVpmT/a
HVn9nIwm1A5b4Vz8OJdFYfeMFWnITgN6Nzk3zoV85fToRBDwniwGrahPa4PCzsug4VE0kYMj
a9SyFW4Gq/j+fOZuMpzGzrN6jblBayEX0TvWv11qj6MxMiWiSiU8idG0qv0rBVH4Hy/C94in
gBRlwTdyARn+NWlAsCbmxO6+v1ZUPO7EbqfCYEWRLREUeDC3/s1LxOi7eYK3/nrWEmVQN+bE
7p3dTClKzrFf8AQv+JgwDwoUL1MLfWI0YK9zhOWupRKqQGdLhHVJR7nOqWhKetGtVl6SK2B9
qw9aoR1T7d5KbnZumI44ip9UwBK4GLSCDN/a/H2vtI9n0XDKWrTlSEIr6GwTY1YEQ4NT11Qw
lFg7O3MsrbSKFqKnFfkiznVQCTsZTau1+PmxiLKAN5zhQvVvZML/HWnAkqyDPR4ndi/F05eB
NdoDYNtJgKWuoJvsid1L87gmK6CA8QXeTfOygArVJ3br8/WSuoGuhid2ScZzsPVe3hb6xG+g
JuXqey73bMxg3aoPWuGiojJoMJ6Kxk+bxLl1our7Fbh8yhJlD2qjzoCpaOLDlVkrRQ8YWHip
k9VjfylVvBcr0svY4lEwnESkZfaQtAtaXu6DfprkTUXjfK1Ia0bRV15RqbC0wtSc6VbO+ms6
mirGVTK1qDlA7QvnNq03yfttdcDaE6M2Rid2O7szMEV2YnezO7CA5YXczOwsZdQO+gJv/fUq
p04gNz6xe5ldD1MM7PlO7Ir03UjQ4zKQ0Ceq/jUV6+Ee4Q9YS8MuGOuSAjKygePCXDQlidPT
2G79MFdBv78YtCJ9Vwf1Y1PRqH8WWg9eEn7OYDQ6mVX5C33425X28SwaStp6NExHRSwTWnmp
awzlBu1OU9GE6nFvWriGiXctsFbyirvse6b6NT05rERcjFvLsCWVD3pzu0Xc7lfUAUN8E0zg
ndi9FM9SlNCj/QCB3Uvxqn+eCGRRB3YvzSviOzWawDvBe2meJKmgKPGJ3XxPK4kbmMG7wCtS
eLfVSr79Xj4S+kTcvyVS812dKJdewe23LfL4GN3TTkUTV66U2apSzQ3UiF91TzsielPRBNEj
8Y1XRCtnNIe3RAc63za0fq+0j2fRRDVlKCH5IlPJGdRgWFOCOSR6U9EE0cvdOpeivaEG8bOm
GH+5qR10tk9ODjf2deYHvtYFLbVPc+U7b6L3uwqB3DvcbBzYveQusjZoAd6B3bv1azJGyd2B
3Tu/mhj8Gh3Qrb+eWJIHxnKyuxeltHCSAL15D+yK/N2thYRvtpeFhD60kOhVTXxvMhWC7cHW
tBoPRNsmoxH/iarUXktjVONnTf6u3UbzNRmNpFAHzEJarBjYOB2DVqSIbrWSv1fax7NoQvW4
moSjXhxP4HaHJU50Q33AyXBqK1lqJv+roW1peRFN1QGvmwqHojhSMrdSemmoY8FkdeSb1/0R
+oChCInSu8DupXfFdybQieAF3X05ywVMG5zYvaWVnPy8iX2TTuxuehdmTyi9C+xeemepo+T4
BV1B7sr9lmuXd4Q9845gdnpHpZSqChaJ+6AVZXc22HHnomF/jXrhItKzVVB6hSfvmP5/zm7g
3TYbjX+znN0xhc4w2CkSg5bU3d0XeNrlHPEommjRig4Rad20gNuKD1pRdzfidnPRvLidmb86
Vaug29AibnfPvL+mJyfnZn4oalFxCatRztWrvrnd7woE9oaTusDuJXWSMlj0dEB3Z+wUFQY+
sbtnF625O6B7KV1NFRQhPqBbn05DtAz08zixP5yvs8szwp45YHQTot4tKtRAk4UYtCRfd38N
OxtN4ZDR09yFULNpH7SCoPZbB4yvyWjkdc7LGplURb1WZFG5/iBfZ5djxKNoIvNGr67sIrVV
kDZsyNfNhtNyyeIHIWlNCqHhrGg0H+br5sKh2B1LIe3M1VA9ER/05nT/O6f7JWlAQZ1uT+xe
aqeJCnhdfGJ3Z+xEUO3nA7s3Y2dJwUK2A7qX3PUUvp3YjnZgd9M7P9jC9C6wCygE9fsqO7uM
I+yJmL+kYqFqp7FRge0/ssRCi2wg1zYXzJFXjutlCr1D7Gzgg1Yk7Drd38bOTg2RdGsS7hGC
0YcYs6TG7l51xy7TiEfBUApz5JabhBAlKIYSg5Zwu7tD0edkNP5ChyB3YarKLCDzjlE/ze0m
J8e5XXWWqlatg6KN/1ZuJz+hCwhe7Sy51lnW4rFdf49QB+gTu/t+mMxAvnlgt/PNAus8vrBb
57fVFHdPWBn/gd36+1WnNaDB6wHd+3Q1FB3BxzuwCz4lMjCAsMvNwp5YDKgfFKMFIlpeG9i2
p0vkMsjoXpdlLpiSSmeRpiGo20Dt5hi04oK4DrKJk9E4CVCutZFHBLLnssZDbtS9a5eXxaNo
KFlWD0V9nZUMVsv5oCX0We5kZj6nowndn1Ja9zmqcPZNVsxNHgizzEZThLRbrp2agPZ+NJmF
/9P55n9Jfa+A/sAHdHs6kVH9pgO7m961B/Ism/VZuqZaGVQXObB76ZOfVhv4fCd26/O1hisr
ntglBYCD2+LLzcKeWAxoskpiTXMTzhnldyvcykhvbyQ/J6MpiXPnXv2PEi0eICNaIUdM1e6b
dmfnhq22LNF7IwxG44NWNO3ei7t9r7SPZ9GEeXHPvbMTPLiPyAct0SPWAb+bjEayBmG1nAuu
rixLhK9vuffXdDQm4u9MNQuvP7T+z978bhG/2y6852Qe1Fg9sLupXcngXeKJ3U7tHtwUt903
xb2mxqgo8IHdS+5akgJS9xO7l9z1cHbGuN0LuoLa2YDaXd4M9kQyX1Mjshb+oM5NwOUQgxZE
U/qgEHAqmpJMi4YbXs/hzgBSO1vS2zGidpNzIyzE3FtVMViPZUUbMuc2qEm4zBkeRUPJIwk/
6lKkEygjSEu6iAZljZ+T0USB4ivdpVxyzmDF0qKyxvvGm6/pySFW603D+FhAv6zZxps3t/tT
hPc4EaF72IHdS/HMj+ogBT2xeyleeAuA5WInduv8UtYUtdegbNwB3kvywuYJNXI4sHtnOOeQ
JAWn+AQvyeHdWxrY5c9gz/wZeq9Vcu2V/d9Qg7S8xCCtD0q1pqIpzvdVSq7MziIbRo3Kkpsz
qnpHW7+m56aSNjFlo4ZWOPqgJUTvVtvte6V9PIsmZNrCBaR3LkoGi/j+tPDeXDShldyodYqW
ZGd6aFFgX9KTfMvCv+Ynx9mjRGOa+hcf9gL5V5oF/9uF97KB1p4ndi+5Cx1d7MN9QPdu/JoM
vX54QbfOrWhS8Lc7oFt/O6mpCFhTeWL3Pl9LrRgoY3JgV1A6HRRDXcYM9kQtnxPX1nJ4GfjJ
DKT5vGSjJeO7nelzOppw/2jSeigQG/hlSGUFQW1lkLubjCb6Iixyqj0aLNFo1nRGDPo8Ll+G
R9HkqO0Qa07qLHtAsErdEmnoURPvZDiN2HrhTkq+6LBPQV6S9R70rXzNh1OEfVZMoga3YNvW
bN/Km9T9Gap7Cp7hT+xebudHbVDE44Duvpklg4vuaEUZ0xNu1/3siGraHdjd7E4zmPQ8sVuf
r5REqD7+iV3AIGjE7i43Bnsike9kwD/m3bfdStHAhzKINZZogzTKZDTCmXILATEpFVXdW2OJ
ZoNS98loKjeqxeelUUZPsamu0akb1ABcZgyPoolG9lqtamNlQp2OfNSSqrsRu5sNJ6splV5y
CEVjKZBl7O7uzfmaDqeXGkJA8qryZFjw+q2p/L+zu826e5oMla86sbtTdiqoxuiB3Z20UxXw
su7A7qV25nMG0vYTu5vaRQIGFt9rm29jne6+NCwwZuzQBeRBdJBMufwY7KG7hIZqRmX2bbej
5GGFqaATu0HJ3WQ0hbvvsiXaMQkWIF6ivVdtcD02GU0o7vmG24uVDOsi6hrq8Lcr7eNZNMGE
xDl3iCOyLzeY2C0Rqxvps8yG42xOmznJ0kJgBt9H/Szt/poPR9UDkhIXsgKq58zS7jex+yPE
9wqBRckv6O6knYHO6wd0d9KOO1qIdWD3zi0lf5FBYcUDu/vSs2TQZPnE7k3bhb0J2O5xYpew
u/u0Xb0MGeozQwaVqrX5qMyqMINYEY3xvRbKbDS+LxXqftKszUB7+UVcdZS2m43GTyyR63JK
5LMEFhYv0ncbpO3q5cfwKJocdr2tZc7mrAgt9cmL/HoHabvpcHLvfh6yQsUEvKBZlLYbuWXM
htOrStcwuZbWwab52QaRP53d/Yj8HmrbusSy9R8rwCepo/67J3Z3TpEZ9d89sLt5p6A9Mid2
6/w2SRnMIR3Qrb9etVTQLtkTu/X5LNoiQK+WE7uEdd5dEjkXuDwj6hMdf/WZLSGcIWJGoF10
DFoQzaiNdy6aOF3WVp3ONraKetUkW6LAF6Jyd0xgMppcTCmHPFK0ioLRzHmi/n+adnsi+F5p
H8+ioRTOF41CUrgX2AVsxflmoFn3OR1NeF+UTNRyLbhm3c+2WH9NR8PxVybziREwl/Nu7vjn
K/BpBsvtT+z2YkADbz1P7G6G1wxUkTuxexletEhg7/IB3cvwSiJBJYwP7N7naykzWBNwYpcw
vDtO5Pvu5RtRn6j5a6JWutXqu28t6OueVshtD/t356Lx17ybZGpCcXuMcqIlzR4933t6zEZj
XLPGf7loBRtxyqQyGqzz9r3SPp5FExrLJZfCLTsHz6gJr625NL7X4JuNRixnDZPkltEbfVqS
wR5qLM9G49/3UoofRIUJNkh+ayyvYnjbNfhKBanTid1N7RQ1uD+x26mdPtDg080afC3aS1AB
ngO79fdrx4kSe74Du5fcSZKMfdIP6E9Tu8uioT5zzyBirUbZ/+c8AqV2KzT4nITdb7hT0ZQU
fq9WIhWZM9gF5oNW0O5WBymVyWjEWbcqFws3rZ1CM5zbgNpdFg2PogkN9JIbeTwqDdQyiUFL
yNAgTTwbDftSy9EzXhtYahGDlkRz3+cxF00IzUQjPzVVIgE1jWLUm9st4na/osEXKopgXduJ
3UvxXr4O4P3sgd1L8UJXD60LPLBb57dbqgQapJzYvRQvJz+mYs93Yvc+n6SCakCe2AVE4l5h
1bfey6ehPvNpULKayTRMZUHO74NW0KKRR9pcNH6Ws9h4/UCnrTWU5OmK5uSRR9psNNXpN2fr
PXtEqCPIGteJgSlvvXwaHkUT/rrsZDVXNkL7RReZ8o6ElueiiYo4CwWd2iUXAxN4PmqNks69
1OPs5GRuuYQ/WvjpwKa87wTe/97zsV1/r4C5iQO6l9ZxKtZBWndg99K6ENUDW6FP7NbZlRLZ
Qqyb4gXd+utJTQ1tljmxe5+vJHamhv58gV1B6m4t1n2rvRwa6hPZfE5+Ym/ViUM08YGtXbzE
04CMB/mUyWgKW2S7WpbCoEPDqlZeGpTdTUbjNKhSjXK1imqM8xoa5Dzo71bax7NoslNUckZH
3Lp6VGh2aImP77DZYzKc5ichq60X8bkHW3Hykiyx8/wBq5udHfFY/JX0Ix5aAOCD3gJ8C1jd
LwnwNQalKE7sXnonyeCs3YHdfTGL5kAO6F5yZ/5qogLBB3YvfWqJURmZF3Tv0/UkoDP7AV1y
KXtHH3zDvTwZ6hOhfGdpFgVD3Q/p3EEXA17iq0omd9F8TkcjxoWLdM6aQYW3RX28ne7FlWej
KRKaGSWuMQ2U711DVIcqLfWyZHgUjfOAFu6w0jK1XsFTRIz6aWo3GU4jZ0POVbtluHVuFbUb
qLRMh1OcePubo34o6qBy5Vtc+Z8ov+dMg0Ft8xO7O2enaNLpxO7O2amC1YAndi+to9Q7KDFy
YnfTOt/VQPm9A7s7a1fAM8UBXULsBrIZlzNDfebMkNU6NxHfp7SjWa4lGUgbaKLNRlNKq1qY
cmmKU6ElRmg0yKNMRsPklCGcVVkNbC6NQSuuLm/lZr5X2sezaHKyKOmKbh2TjDZJ5SV9zJxv
+0I+p8Np7FSIhWojQVt/l+XsBpf+k+HUUmpvvo371KA98++k3T9afi+Dq/aA7mV3oROAalId
2O0puwYKyZzYveyuJlQ/7oDu5naVsLPjAd36dIVSeDOg4oWBXXIfO5BBuXwZ6kOXiUyUsz+f
wKpHMWjJfewgaTcbTbUw6tRStYEpVR+0Ym7abe/B13Q0ymKx20ovqqPF9n8AAAD//+xdzY40
uY18ohUoUpTEF2hgu59i4dMe1j7svj+WrEo1YA8yv0iNWv31uGx47EOk0VH5oxBFRvyTMeKa
stBF0W6kMtxi4zrAqkamiRAVU9TebZG18oW2m6TjOqiJ5OqPWqRm/DZFu1k6TfwZay5Y/eUB
l4VZa8Tv1Xb30szjX9gS/sQu+JT8ab34P//4+z/+7x9//++//Yf/Uf/xX//7t70N6Fjr+WYt
Bsqw3+H2fY/voUVXoIEnXQO8V/BT9eUAbCIY4L2PWbEEz9U9sVvvMReKEBd0z/QE7xXWFosK
2ihygPduTFSTS0zwvP4AL/is5KsWuZHd0e7kKYQFiXLVrNa1gg45ftGKMerSLpoxp9hI4qZN
siqxMiiXZU24cz+Vyx+TbGIroy4uzZxOB8/Y1mxlorb3qyft7R4bShyGPzlbbr6pQQ/sV5hL
MNPFNnOSjUql5rtx39C0AjtVr7F0LBd9v5N0xPfKj7Hw7LtmRunIVLnvVdf9TVwQLfdwSEP1
3hO8V+9lSdrAqYwB3nyAX1IF+x4P7Ga9Z8kaeI42wJv1XkvU0AjHA7xX79UePwvY2/rALjnG
P/N1+0/tI8uj38lXCOFWuXQRpWa4S90KNqWeH+PPsZE4+LbSupQqDBqSy5KDbxcx51Ymc2xC
uIUC9w2rZQb9u3lyBf6D2jsv9faR5HGLjQu3Fr1e+THdkeHpjhWtwCwXHSOzdLRkqb7PdEHO
ndGGxiUJRXbqJPoxTccVay/+7qh2/wdKZ85K9CX3vtsSMbuuTxUNb/pEb1Z6LRk6QDLAm5We
+uIBzn8P8F6tpzWJgh/bAd76GyprKqC/3YHdq/RaTBqDanmAl2i98zHrPhI0+r1cg6jqxWvM
RRXOnKgrmhzrhSPxHBsJdSSVqpBKz1h9Qpaoo9z62b35mGQTsq2Thd1Mhd2ieYmTt2u9c4PE
PhI0brFx1SY12oNrtepfFDQxeUUkAPOpMfn7NJ3i0ij7HjNHHgiYIhBXLSntnZtxztKJnGRi
169OBvVbiKteWm+R1vuO0p6LuPAoAetSB3iv4OOSfOMOTuY8sJv7BbIvOnDz5hO8V+617F8d
MIVlgPfKvcIpo0/hAO8VfEaJCtjIPsAr+jjLRcllBGr0mxEUnXP0PVpVQ7td0hLrx9LOD9jm
2Lh2U9PIB2ku+8AnSFYNX5/P6Myxce2WXelZzsQRaYcKvhWdgnxaqvx80t7usQnpZlqMpGbX
SbjgW+GrwxduibN0inXfXuSYbutobBQlXRKscxoE+TFNR2KK1ZQla85gPh9NvjovwfeNdola
eqqo0e8A7xVRZql3sJ4ywJv79TjB2WADvFfKV0sVje1+YvcK+SKJGpirNMCbtxq++BDY0T7A
S/r1LmotI1qj34tviCkTV3m5+/u81ac4l1PX5fdpNo24M7kYFpKC1ijbioW3ndYoP6bZ+A6m
KiuVOF7fm/JL5wE7fURr3GLjgoDM1XdrriK6S1dURqyYK3fJ/6tH7TadUsQ/PFSrVlG4w21F
ssD1Ce4sHcoPP+wIp0Gn9l4nuD/XPVHV714F17AB3rvKUo0iHagDDvBmrdfiMwBKvQd2r9Jr
LeWCejwe4M1az8JUFw2mfoI3a72WpKFP4QFecYJ7umT5CjwSNvq92AOmXHKMYlLujEZ18Qp1
dKn1JtlUk941wo4I7ejNS3xdrrXeJJuwD4pgbimuj1Advkjrnc9m9BGwcYuNqzbOrlhJ1O+8
gf0ZcdUKOno+mD1Lp2iYKRYupfizhsafrDB4cjrnwxnTdLKQb/mkSq4VHp0pU0r8pfW+0U0x
dJtlsPl3gDeLvAjWAeOBB3h7QY8Lev51gLcX9BSMuTmwm0UeJ2uoE8wB3l7Qowbbej7BS0Te
xdI7Ejf6nRSEqM3lqlp93WgC5ocsKujV06LR+zSbRp2jd6p1RbeCftGKkYxLkTfJRkvLxlaK
xSQDKvKWyIirgt7I27jFJgp60W4oVJ0RgzdnUUGPTgPA36fplBL+nQ8yuYItoWsKepyvTm1n
745ZCTehHGbzghpFvgp6K0Te9xT0ij+MYMrtAG/WepY6g703A7xZ6/XUCzqScYD3ar0efS/o
5M0B3nuXlf3GoYM3B3jvXyixCmFDagd2ida76NAbERz9TixCThxGi6X6Bz5CONCC3hKzlauC
3iSbal2FpVRiA6sSOw5vJ9m41vPFtyj1hjZNrdJ65ULrjQCOW2yiNKdOxrWRWgfrCX7RirCX
bBcNepNsiqqZZXO5ZxUuT67wqriu583SyVooF99NUhGwsE+T3aC/u9QTWOrdWDHAQI0VWRo/
2esvK9j3NsB7l/3cEppdfmA3i09LtYKjAwO89R7zIwcYnQc+wFt/w9J9DSUwl2+At/6FErsG
Ad0IB3iF/DyVOC4KRlBIvxPe4D9e1VwtskKIMDnt16zQ0q6tzjXBFJnwcXG9JpxdTBNYN/WL
Vtwau8hdnmPDLr38rphS4Y7GJi5Ra3w66/L5mL3d4xJbWLXKZEW0wtMUS4z+zuvz79NslP2z
3VrV2B3AYm2FqyvTqd/nxzSdmJ5vIaMrWwXP8WjSVPJ3157/RkZ/LTUGwyoGeHONR5IxalN3
gPfKPS2+GIJvzABvlns9VdhC5wBvlns1aSlgaMoB3iv3wq25gMMsA7xAU+R8IfdGdki/k+cQ
FS1xsZdD7zXYAGaJZdml2d8UG0kxZNx6jm5IEzAVyDetK/Qenee6zLGJ+BxupYtGUA2oxddk
7rjiO4/97iM55BabEG9EvqeI6GIRuN9ukeS7KGxP0lGhXHNX32HEKP1WyXfh7TxLR3rrvm8O
l0yq4FzSy9v5R5v9NXhgdKA3qz1OHY09HuDNak8To8HHA7xX7RUXHw0sFjyxW39BzTlyL7D2
hid2r9Kr5JoCFHpP7AqdVy9GgkdMRL8X4aFdeqVipFnAw7G4aIXOu4jwmGMj/iJVMe0uq58/
Fub7suRUmS903hQbl2yuHhv1OIRt4Kkyr5mr4HyeAt5HSsQtNq7YuFql3Pxb1wpoiB72gCuO
lfuFp+QkHacgLqashkUmuG+Oq5b0d17ovEk6IvzIAO+tKhXU1HmujPzSeb+P0V9PDT1C+0Tv
lXuPYzFQ7T2xe8VeuPcR6gFzgPeKvej/BGs4B3az2AtDblDrBXSz1LPIikC13hO8ROyduzrb
SImwewke2lrptRKRMhg5u0rsXRT15tjEIS4ZudxTbeCGdVmAx7klxxwZTtxdSxTfqbYI1QO1
Hq8J8DivHtuIiLjFJlSbNNZWzPUEwRZ/S2pgen6KO8smUi7E90nGlTrouL3K0/nUovpjmo6I
ZSFRa/4P+BD3Zen852dFvsHhT8CVa4A3d+nl1ED1eWA3d+lxqgxarg7wXgVfa2qG9hEe4M3l
WvMvDvidGeBv6BUFnTAHeInCOzfXtZENYfdyO1w1lppdwVM1sHfTL1rRplf6xcI7ySbObH23
VEtvGawYLTKltlNR9DHNRlmtKlVtMRGMqu8l9a92IfFGMsQtNjEQXCizi7xo1ANPY2jNKTTx
eeV4lk6R6h+fyOSN7Dm4nLcmkvfszfmYvztWa+++mxBuaCDgayD4Jzv85YRO2x7YvWss92QE
btMHeLPWa/516qj1yxO8V+u1UMBgMv0Ab67VusDsYEfSE7v5KZTkwgjUogf4q5XeCIWwe4Ed
LubJStfsqztoYLFM6V0sv5NsalMhV0WVNKMelmuUXuOLYt4kG81FXBy5BHeph6pwXeGVwvmi
ajwiIW6xiZH4rL25nFBtBJ90rrF+OaXzPk2nlFaVyd+ecLTZaO+XzS42FbNsqESuod8eM7ya
9xJ6C4Tefnu/YuCpzQBvrqNw6nA174HdXs3LveDmfgHeXs2D41af2O21vNzBZ3CAt9fy1EAF
McArFF4+N3yxkQhhN9M6mj+ErZdOjG7tdtTyJtnUHvFbvZpVKaheXaPwynlr3iwbV6sialkL
M9houKiW57/ir560t3tsoirHWsW33S3SnuEjwSW1PD3bGr1P0ylSSu/GcWhbwbsTVy2p5Z3n
PU/fHVOuJVMW9TX9pfA2Krzv8vbjiomAA7tZBGjyXTpYyjvAm4VeT2jayYHdXMgr/rVBj4AO
8Pamy4Ym2w7w5lKe4k2NT+xXy7wRBmH3wiDCiqQ2Vt/JMzj+uErmtYumvEk2zsRUpLUqoH1H
XPPVdbxJMpqrVNHKZox2+KYVZuGRqPGrB+3tHpuoyJXm+kTFH7gO9hjuqONN0nGN15o0IylS
QZPURTkd5TSb8WOeDtVWezZpXdDZpb9qTseX+PpldKp1xcHjT3b2Aw/wntDNiz650gAtmwd4
s/Q0fydBcTzAW+9w+N8IwePTT/DW37B0SdbA9XaAt/6FUloCh2Wf0AUflCtPPxsRFXYzoqL6
I2hxukeEZ86uOBG/MvWbYyMp+rfi0NXEuqImLyv6dXPvF9pzik3M8bZSiTplbqgL59fb+tkI
qLjFJmz9imu1Up2U6zXUhHnFVL9v/i4qjJN0lHuJERerrTW4Jvflvn6zdFxFV5PKJcqM+M7g
5eu3SuN9j69fT6gn5YHdXIOiRBks4w3wXrGnxT/TN1z9ArxZ7NXUMjhcO8CbxV6PLAjsLxzg
vWJPJVoVsL9wgFcIvqta48ipsJs5FRI97rWrwulBa44trweAp9hItEA28eVdrXUwEUXWVE77
aeX0Y5JNDPMKmebsMolB66NVE8B8nkxoI6biFptHFFErqqRUawctF1e5+p3SeZ+mo/5/StW1
eFYpYPvCGsGXzc7dXmbpSFeh3oTYyMAPwcvV7we7+qmv7KhQGejtp8pcwOa8Ad6u9jqhw8AH
eK/aK5IaeCT6gG79/TRT6mDU14HdrPNaogo2Nw7wijPlK6OXkQhhN8M6WumlSi/d9/Nb0zqu
XP3m2ISrn0XOsbiwzhUt7K1x9SsX9htTbMKIufrtIe3cBU0oWnMK+7DIv37S3u6xCVe/okVa
tdqrgB8fWhKlcunqN0untIdi1az+rIGxkatc/eSidXCSjnDvLsNdunLsLV6ufrt13je5+tXU
Mxg79YneK/eUUyW0T/8A75V7NfsmFm3SO8B75Z5mf1VBf58B3iz5esTCgTNLB3iv6KsaRTGw
eHSAv/o0d8RC2M3IDg3Dh8qqtYOma4tOcy+Le1Ns5GGjaNZJNFrwdtr7Nboo7k2x4cS1du0u
9V1UwLW9FaqCT32pPx+0t3tkwqgvnIKVS/PbA4ukJfZ+fHpv3qfp+DvjmyWuqqUL2Hi/w95v
ko5/oPxD3zKXzo+0wZe/3ybN9w3+fgVVKAO8V+VlTk1AT5UB3tyv59ISPgo7wHvVfK3+6QRr
OE/s5sKtRf8IesT8BG9+ClsiQy3ED/CSA9yLpXdEQti9uI4og1lR0mJ4LNvXzwRPsgl/P2dC
nbuBnmuLZoL76XzFxzQb5WxMHE5yFQziXTQt8rAovX7S3u6xieleycSVm5FxR1vcvt7fb5KO
35VSH6HCGnpvr7/fL5+1+3fHtMdUkm+QrOJ1ytdQ8AKR923+fgxOOQ3wZh2QE8Fmzgd4s9Zr
vs0B/dsHeK/Wa5Q6+hsO8OamzJ7iSAEeDA7w3r+Qo3KCujkf4CXHuKfRqJWOUIj4H7fUnlor
rvdIW0d9H10iLjnGPT1bm2ZTu2VTiX8yGGfmF60Y226nguJjmo2S3xKrZCaoI9Iqj79TNp9P
2ts9NqHbzHxfwcWKKeyKt+RU+tGefP2o3aZTNGuO8RnfYTSCh2m/2ORvng4Jx7bPWDvh5tQv
tffn1d5uk78cdinY8jrAm4spkjqDRccB3l7SywU1kT3A20t6xOAY8wBvL+pxAQNuB3h/Ua8z
bvQX4CUy77TUUikPKXE3tKNT86XKNIOEvr6mN02mhn0FtUy+e4JdC786s2OajXLjQq4jqrUK
1/TW+Pxd7Cfy0BF3MzvyIyG5FOOS0ZPOr/b5m6ZTpPijpr1zR/t2v97mb/7mmN+Y3EVV2eCU
uddMxgqR910+f75NQQ2dn+DNKuBRA0Ptfp/gzVqvp1pBT/oB3lzSizlFtEBwgDe3YlJqoPvH
gd1c0CuporveAf7a49tKPOTE3dCO0lrXUnIBe+V31PMmydQwcy7USxNwp7CsnHfaoDdNRjO5
/hZWqbXAVjhfHNkx2LzdYxOFuTj/0eJKQgnUravKeadeOO/TdJwHd80Pb8naUfeYry/nzdIh
pVKpaqmFQJfMv6rVH3+F1R86xLd7ogAs+Cx4bBeo4u+xH/TlO4OVsQHeq0aoJjgB44ndrIgt
dfDE48BuvcNCLnENtOIc4K2/YDGO9hrMkOaJ3fr3iVrMGoG/4AFeUfk8VV2uU2SorjvRBpwo
jrWkFG0uvMAtSFoS2HIxpzzJRhK7IFbKVrT3jrGRJQ4uufWLetTkvRHruWYNryA4UGfyzPEP
UxEXpU8ZmutmiIb41059v8KWUbOg2UnYf/WjkYsq+yQdjWgT146ZuCm4eferlrQzngbQfMzf
HfPtSs9s4XYJDsW/ap8/3oCwJd/LY5+WAd5+2K0dnW04wHvlnpYYmgHLiwd4r+DjqAuj9nkH
eOtvqETJ1zlsTRjgvZKv1SRgNsiBXSL4LgpTZYiKOykHnLI/g90Xr5xzQXs004oGkivH6Uk2
4TjN3C3nTnF+jwq+JaZw5wkU0/emSDaRwlRKZ6wqxUuOU7PZRUdjGZLiZtqJVqMuwUkNXGT8
qhUGhNTOpnrfp+loUeHamboyuPfzi1b4Z9NVtX2STXHdatXCuN/3+Kj/4F+zAvpv4T8oYR8N
TtkO9PZ+st7AJvsB3iz1FJfLA7xZ6lkqBp4FDvBeqef6sjVwfGWAN0u95t968Cd8YldIvdNT
Ll+AdciJewEW2V/hLDEkwehEwSKpV0/Ndd4n2fgHiZxP5HOVjnrSy5JqmEu9i9re5L0pImRU
qkhFW83WSD3/cv7ySXu7xyYaFIvfnFZza4za6yxqa5R6psPfp+mU3vy98YdYqWiDZ3tXOIFT
uTjtnr07pcfEdSuRfoDX9qak60vr/T4ehC1RAQvtn+jtjWVFOjop+gRv7hjIvulBk0cP8F7J
pzV1MM/pwO4VfKX6pwQ8vhrgvYLPehIGNx4DvKK9kS8W4jpkxc0Ii0yNXCNxVJFgm7sVnn2X
km+KjSTxdYtzJJYxgSN5MhmK9a/HuXI2LPExfW9KxMs2i1iOgo7vfbWx8eeT9naPzcPYmFvO
lLWogpXxVce5pxNg79N0/KNTKZS+qv9POF5kyfbCTi0I5+9OrUVIOimbKCzIpx62l+T7ZgtC
M1BCDfBeCWWWDHVxfmI39+txqq3h08oB3ivlu6XOqD3bAd4r5CPMhNFj+gO8eauRw1AN3Wo8
wSvqelfVljaExL1sEREqj4b8ntGlKi9ZeWPW83zlnWTjepW1KftPJWC2iF+0QrLaVR/VJBvX
QtRj8rrZY0gGm2JZcUqY22mG3GDzdo9NVI60uZDg8NlRMKl0tnL0h3HliyPcSTqliGk041bc
YWeFAeH1DMssmbCHjAFs8+0ReKDysqT54QaEBRx8GOC9ayzVyOXGRzMCvFnrtaghwv6DZYUG
uBMoQjmZoL3eB3jvPVZKVsDQrCd2s86zVCqYETjAS4p5F640fWiJe3EiUk1NYsMmAiae5sk9
/B9saS4W30k2jTiGTShrY9D5JC5awKbbmTL6mGajWmOgoRXzpxy1UlwS9XJeLvp80t7usXmU
i8R3KhRpzhkcDZstF/3BfPBiNmOSTlEXqzn6BWIwHlZ6KzoPS74oHM/SyZWrS/FIDUc/BH7V
1MLwUnrfbD4IN5cO8GaJF7bRBC6vB3h7OU/IwBPbA7y3nGcPGxKwIPrAbi/m1Qaetw3w9mIe
GViyHeAVIu+018iXXhtC4l5mhfguzar2ltXQfPDJrKg7xbxJNi0zR/6duW4FaxKLinmXIm+S
jT6S73LjboT2gCxq+T9tA/t80t7usYliXq05al8xlwE67Cwr5v3yUbtNp5Tc/dNYxDcUHa5N
LirnXQxkzNIh6t3vTOm5KW6Y/SrnLRB532U+6JsTVOs9wZu1niX/7oFHZgd4s9brqcPRcQ/s
5nJeS5nAucQB3lzOK4kNdAke4L1/oXAEaqJG2E/wCq1Xzici80isyPcSK8SymNQW/11Bh6BJ
j4UbWm+WTaNerDTzJ6KAPf+LtF4r50WWWTbqC3bJVRuhCbRr6nlMdF45ziOu4haZqMzJI6qC
I48a3AsvqudRPq/nzdIpvj0SJdIuxODOeVk97zy4ZpqO7+pzrdylaQG/vX/Vep58hfsg+Iis
qKv8XJ8/TZyxWvKB3bvs55aqotLpAG8Wn5bivAQ2+gvwXvnZW2IG/c0HeOtv6JvdyHPG/sIB
3voXit+4hjqwD/CKvkE7LzXmEaWR70VpWI7TV63+X3DW7wq1f+n8MkdG/IMUHXb+rzDyhq3+
VrDp/byZa47NY9NSjZmqKwJwmIuXVIHjZ/zVg/Z2j03YWEv3dyEqp1lB091F5tdSLzY6k3SU
K/vGoFTfWXZ0GnhJBA3l8w7V6ZvT/ZXxDWFRKoLfnKk99e+uPv+tnP4aYZ/JA7u5yiPJSNHs
4id4r9yL/JemYLHxAO+Ve9ZTzeAZ4gBvlnstFbRgO8B75Z62ZB31SjzACzQF97MPva/CI1Aj
3wvUMMmdS5wpmaI2AH7RivbBeqH3pthIys7BrJXWWUEPi7hoRbWRz+cz59i4dMtqIr2E8R76
1Usrto9MV3XtEadxi03MAkeoNBN3c6kPh52smQU+71SdpaPi26+Wi98dbuBI0irBd7pT+pi/
O0bUG6k0CSOol7XzZsG33eqvJKugp9QnevuZnqH2FE/sZq2nYVcPrpkHeOtdjlwOzeCqPsBb
f0PNsWCBRm0DvFfrVcIHvwd4hda7GAnOIyoi37Hvd9mmYo0pd20Z7CmJi1ZovYsYjzk2kcjR
uXehRs3AcTJZ4ibnWu/c1XmOTTzY2VlkkUYVdnVeovX4IjAmj6CIW2wocXMRXnORztLBJmG/
asECw/m08Po+Tae4uifLMUab0XxpWuTKcxqy8jFNR4SLiOs864paWs0q8ZfW+32s/noiOLl+
oPdKvtKTb93RoYIneK/oq9m35aCHyQDvFX1Z/cuDCpYDvFn0+Y1j0Dx5gPeKvhZztWB974ld
Ifn0QvKNsIh8x8E/1JtWqhGwIIr2Eq6YdLqu7k2RidNc1VyotswChk8uOs1tV0dsU2xipIyp
5NabUQVfBl7jhswXnpJ5REXcYhPazUxbyVT836B5Ai1J1XNp9stH7Tad0mqr0lrWzg0sk4Ql
9IJnzeyib3WSTli8s+8tuhY28NWhydaBl+L7Zqe/BoZaHtjNHXs5RBvYsPfAbu7X49QyGtR2
gPfq+C5JGbWnOcCbC7eWVNCuzAO8+Sn0zQ2jiQoHeEW/XjtPTM0jIyLf8e3PvvCqxfDpMzgV
lHhL0mxLv2jin2RTW5dSVePEHLUDTUtGeSxfNOxNslF2EZGlFW6lomyWHBHyRShgHgkRt9hE
AaiUrP6QKYnCVbAlB7jEF/XjSTrFd22+k8hMtTfY/XhFqwnn0yC9j/m7E1aSNffipCrszvMa
DV4h8b7L6U8JrEQN8N5VlnvqHdUBB3iz2mu+o0ZPwQ/wXrVnjxBx1Bj7Cd5cs61xPoLWbJ/g
zc+hpGgJA5/DJ3iBojhPIPA1eMRD5DuW/SHcRF1RSO6kslfttYsqyySbGHZSo+b/QPso/Jol
J7gXHVSTZDR361oLce3oJyWtGKW6NHXOIxviFpuHqXPpvqMo6mICfHdW+cCcJum9T9MppRpp
rpVaNXDYLUaKl9TzLjYWs3RIG1GzLNkYN/t7BfP+ebG32+yPUgP7QQ7s5koKp44GoQ7w9ooe
M7q8HODNFb2SKmi1dWC31/MKOjHyxG5+BlvqYMvUA7qikicXoxgjFSLfS4Vg667rrGbxZRc2
+VvR0HZZyZtkU7uU5u9TxJmhvi9LCnmtXHTnTZJxzV26cOXojocDO5YU8n79oL3dYxMlOY2q
MWu4OXc492tF5Yv0bE/0Pk2n+IOmvjH377YSPKu6JCb54ZB4/azdvzv+9pu13Gpx5Q1L1Vch
b4G2+55CniQz0LtsgDcLAE3EYE15gDeLvJ4amhfwxG4u40lqcHzcAd7eepkJLZId4M1lPE0G
9w4c4CVlvItZyBEMkW+GdhBb05KJKOOhHUuk3lUZb5JNrT0cH5v2jAvXr6/jTbLRbMUfnVKM
DbTYXVPHy2YXh7YjFuIWm1BtzoVErRXOsNT78jLeJJtSWleq5NsvyWB/wJoyHhNfDGLM0qFm
pFz81nTK6NDtX7OM9yUef2hMTV6hV36yy18p4BDmAG9e+in56gKeMR7gzQLUfEcJh8Y9wVvv
MveSlMBh4AHe+huWLqkraEQ7wFv/QikxFAXa+wzwkr7BC2EwYivyvdgK1za9tVy7aC5oSctW
SNBLo78pNpJYmj2KWmIClqr9ohX35mH2dqYLptg8pty7SamP0z10MmRN2+DFXmdkVtwiE459
vlMkf1Wr61tBZ4GX+PzxVbVxkk48Zb416M1aE9CFcYfR3+zdceHpi6X/X1cR8BzvZfT3443+
egxsYd/JAd5cjqJEApejnuC9ii9yLlATuAHeq/iijsjgwPcAb1Z85hIJjDIc4L2Kz2+cvwCg
ojjAX6z4eIRX8L3wCld8rdQwYaMCH2IuUXxXw8BzbCTlakquXo1dLKGKLy8pOl4sw3NsYq7X
5XjPZNIr+D4sGgam05iUzyft7R6bEG/WtfmrUCopWLGnNW42wuetDLN0VFi5qDV/cSq4u1gl
+ei8mWH67vhCZBaNqkRV4Tmel9XfIsm33eovgjkaeC4z0NsPmP3NBZXKAd6u9jrs9ffAbtZ6
Lo4U9HIa4K2/oOZIKcNu8YHdrPRaMgOnlQZ4gZq4MnXmERTBNzM8JNeuoqq5g52Rq0ydL4z+
5tiEZ5+/7aU0NgZl6yqfv3Lu6TxHJjydWWpuLTL+0PTsRcUwOZ8S4RETcYtN+PyptnAurDGM
8LvY/M2yiXFgKS71Wo2JpJ02fyWfny7P0hG2MBcyDd8k0BrgZfP3823+mt95tA1noPfKPWVf
bcCs9AHeK/dq9m8b+H0e4K33WagnXxRRb+cneLPg6/4xAa2Inti9gq/W1CqYqzDAK0p7dqYq
fB0eSRF8M8UjZykUXQ/WGjoWbCsGYS5Le1NswufPufTetImggm/F3Ftup05yH5Nk2L8MhbOo
UHO9h7UTxkVLBN8vH7S3e2xCu0npRiIaVjBbjZ2vbP5m6YTNX46QM+21GtyAt4IO0cXmYpKO
vy6SKXMzqw1s9XnZ/P1Im784C0Nt/h7YvQovcwoHTXgsOMCbG/Y41Y4aOR/gvUq+c1J4cPkA
by7bWtIMTi4N8Obn0Lc3DTweHOAFQuKxuTlbekdCBN9L7/CvelbJPdeKFifykpX3cjx4lk1t
XXtX6024olMWS+aD++nR+sc0G2UpYhQpEQZPOy/xfjnPh/h80t7usXnmQygV33lntr1JbVdG
f7N0ilR/xJhd43GHo82WGP1dzQdP3x1z4U0kmbOBwfKv8eCf7PNHyTrYcz7Am2VAToTOPgzw
ZrHnKzs8nPHAbpZ6PVUBS1EDvLkfs/l6BcrlAd77F3JodLAfc4C/WuqNaAi+l9rBndjFXith
bIH6Bn+91JtkUztRJu2txwDAViuYi/HgWTaas0TyXPY7A+4e/ZoFZM5zIT4ftLd7ZKL0w1Kp
CLdO1uDU1yXS6GI8eJZOzGxHlnXxxxgtj2xw+ZumQyVXV8RauBLYmfKSej/S5S+nXEFbygHe
XEgRF5YFDe54grcX9BhtMBvgzSpPUkV79AZ4e0FPDJ0RPsDbC3qPRiawnscrWqcunZx5ZEPw
zdwOy7lpI6vFwFaIDbkds2xqFxIViTNysMSyIbdjlo1yi3Y5FxIuJtDj9C/P7eCRDHGLTRTm
xL/IEZPcGtPX9oHdsPubpVPE/02Ww3GogHvmDXZ/03fHShaK1kNuGQ7Oe01jrBB532f3h50R
HNjNGqDFK4ZW857gzUqvp4qmGA7wXqVnvrgxeDA6wJvref6zlBtJywHeXM8rydcsND3mCf5q
rTeiIfhmakfvtfvS3n07D1pGbEjtmGVTG2fy/Z2zkY4GXXy53d8sG805FxPqHR2RW1LOuwzt
4BELcYvLI7Sj+7euRc+h4lYrX+32N0unlN5zc21EXRnMz9tRzpulQ1ofUs9lZIbz8/6abn/8
493+bk0TgHMECx7cBbr4uzwIwaamJ3SvFqGauqK+DAd4sya21Cr4yR/gvZqYRFJFAws/0Vt/
RaUwMwb3Zk/s1r/P5VYSX0GwmYgDvEQTn+ku1yojUoPvxBzUZORroLqILN1XRYhRXeRGc5rC
/D7JRh42y+FIE3MR4MyTLBFeucuFJp5iw0mNLf5Tiu9XwB2YX7Si/kkX9c8RqHGLTU6+3Ctp
YerSGa3m5iX1wnY22/8+yYaS+paOwz9eFQ5Z96vWWGBfmNFM0iksEXtUOEyF4YGiubPF310U
/3v5DzawxjjA28+7wyoNPu8O8F7Fp+WG4jvAmxVfuB6CU3UDvFfv5eafEnDMe4C3/oVFOBFa
mRrgBariYRt5tg6PYA2+k3bgm6LM/qFv1qwIuJeqa9L6LhXfFJtQfC6uNVJcioAeO7Kkcy63
elY5/Jhkw6lZNnaZn3tDh4viohWKT85ExeeT9naPjYs331Zws27aBA3WTHmFRJLTE+L3STau
3WokKWarTIXg0JMVDeIXLjsf03RKCzHeqXQRBUfzZl12XorvN7AfdOlR0LPQgd7eVGboUdYA
bxZ7mqSiowAHePN9NvWdNtrJNtB75V7xW0fgfR7g7XKvE1aAPLBLyntnX3lfgkeEBd/JFWjJ
P++mvmB1jr4ziJBftIKNnub/vk+ykaQc6RW9d3/xwerrkn7Af9Z6/w8AAP//7F3LjiQ5jvyi
EUiRFMUfKGAzP2N2D3vYmcPu/2PJCFceuuFedLVSWVkdwADTB/PutPCHTBRp9scFeIqMy7Yu
HRszt0qSdaRZovUQLs68R4DFLTZYwD8lLforTDk5weIXLTnB7xe7iik2rtpAEKoxmgnltd4S
OnY2ev0+TYdcg1u0bXSyfDLza4BlldT7IgfCXjCbdXuAt7eWSc2aJR/gzR0DWJJ9YoHce38x
CmGSHX4c6L1KT3tRSv6JA7xX6XWN3Nxs2N0T/MlHuTTCK+hOoEArUTsCM1B0sZf7zf2iFYm5
V1pvjo3rtrC4c2UUq3CyTBkXrRB7dn6UO8sG0BpajwM2TJbC/KIlzjR0niVHI7riFhvXbbX5
Y9ZdwRKlPZBgxVHuVa7IHJtICEHXRdC5trg7WbG3JkrufJJllk5MXQtZjII1TpbEZ9s1X2rv
S90HY8GEbB3lCd6rn8yKZe1KBnhzw14tWfPhA7v1HpNKyX5iD+xeDR82PdlsqQHevMvQUi0Z
FzXASxTeeQsVjdQKupda4XjmaGdikmROfVy0gM2jN/Bs3Z1ig/45InNJbWYI6SA8XcGmn4a9
vE+zEaMwCxIW6HnvwSXlvItRKRqhFbfYQGmdEVTbI8sZsyJixYFRxVODnbdpOn5TtFeuYcxc
kzWRNSMsFeQ8UmSaji9FKOgCrzqxNJ3fcoTl72E+iP4w5t7CA7t3jYXmW+9sjtIB3qzztIgk
rX0GeK/S6+GFk41QPcB777Jo6ZrcbwzwZjUaHeNJk84BXqAnfOtyvgKPwAq6F1ghBqy9dezp
9tI1zf/YTpv/3ybZuGyLMK8qnf1CzZoP6pIR0tOK0fs0G78hFbgZdEm31CzR4b7qX9SNR1zF
LTau2lzhCTSUsA2qOekaVy05u70o503S4RaPmj9mj+POrJPLkvi4c9vs93k6FHPkZNCEHpMf
n2ib/dJ6X+w+WJmTh2UHeLPMwwKSbdA7wNvLeZR1oxrgrXfZF44CSXvEA7v3HjctkHaYPsCb
RV4rHZINU0/sAhlRT+c7feEdcRV0J0KgFhOsiM1693/Irbtx0YoD29Nu/7dJNlhiZKFSDBBJ
ukW2rPg+uMQ7z/CaZaMUU6rhCdkwOYq+pjhZ4SIvjkZYxS02UFwRgRqZb8hUk82GcdWSE9vz
KJFZOtyZY9Pl+wloPa2JluTFXZ3YztJhVTRlBNC0Xn2d1y4QeF/lPCiclAADvFnn2Q2X6QO8
Wef1YpZ04BjgvTpPrTRMHjsO8NbfkIBKS5pMH9i9T2FvvpdP+o0N8Aqlx+fd8TTSKuhOhEDE
4hpE7zUjZc1l/aIVbNppr//bJJtagDSa/V1RiHB2SnWJA04/7fV/n2SDxcLxV3oV60k3OFzS
NelC72JLMbIqbpGB0ltjQuVWWwzdJsVEX1L8unBZmaUj3KWKtsiseczC73NZwX6xqZilgyrQ
EYx7s3Slde4g6leXevQZ1oPJ3KkliVPLxkN2W/xx6cmy+IHdu+yjllaTiYoDvFl8WnhZpz3+
HLv1DiP4rxLpS8nRnwO99Tf0HbwrgqT10ADvlccSrYDZ8/gDvEJ+Xli+0AjSoDvhBq2oKUPV
3mvDZIUh6qYrCo18bnw9x8Z1MRGLS1B10Z8s9cdFSwqN585rc2xqoe7qBnxX0BGzRyuTuRN/
VDh00Tc4YjRuscGC/vxinPSjtXRkC66Ym60XGSdzbEJ5GTSLsWauvWdz+dZMhpy+OO/TdMhA
iLorUAZKO1+/Mk6WCb2vMvnL1sgP7F69R1SMs11lB3iv3hMu2VPvA7tZ79VW0LK5CQO9V+9Z
Leif0pzeO8B79Z7WojWpSAd4hd479XvwVXiEadCdiINWGvWq3GIIUDlr6rxkU8ync81vk2yo
hLeyAIloHPsl9d4K43fXe2ea4n2STS2M4a5l7KR68hCoTrbu/1EhXZg60wjTuMUmpJsCuebr
ZKZpvbeielrh3PZljk0oN4lz/xigZ03mJ0aRcsWjdpF0MkuHQfThMASdsoX615jIN7b4kwLp
QLaB3iz2asl9JR7IzTJPCmnWMOcAb77D2gpnz0E+0Ft/xbBnphtWzrR5ECiGpCPKPT1RHeAF
3/dLw5eRD0E3szuqdoCKqlaTq5VftKIQxnrR1DXFhgpV39kpAzHU5EA5LYnHRcOLtv0pNqHY
oqezSmOtyVOpOpmncMPdj0Y8xC02UMwqRKOvSqvpkYoVxx4u8y42FJNsWJtviyqL7ywkmWK+
qH3wPG7wfZpOxA36+w8Y8YnJQfrZuMGXzPuV7P0Akp+WD/RetReeM8ld4YHdq/ga+qqTrewd
4P2avkvyzO4DvVfxVRcVmuzFHOC9ms+iKJtM0Brgzz7KHQkRdC+9Qyn8/VocFtb0Ue4S05RL
zTfFhkqNdjWt1JUeARS5o9wVGcadLzTfFBuXb74QM0Y6RMN0XtsSk5FLzTcCIm6xCfnWIc5x
hRny/jywoGvgemZkkg53JmZjcR2rlO29WzMzAhd2Q5N0qPm7o1Gw9M0fpM9ypz5rL9H3pS5/
VqKlIuny9wRv7tgLq4Zkp9QAb+7Yq6VhVisf4K13mZQKWLLrcYA3i/mwVkh2+z+xm59CKx2S
J8wDvKKwdzUuMqIh6F40hD9+0MC6xEqVFRJLhl9Yz46h3ibZYGm9xZRm86eCk084LrEXQaWL
Q7VJNsIuv1nIADAZmIxLjggrynk+DI1kiFtsoDQ1QiMnpB2TU9uLfP7OzVLepun4ZiJKYWIt
4i7Slb01B7gXDXuzdFx4V0bl6A9N7rBfwR3f2+evZhNaBnjvKlt7ManZzI4neLPWe+TDpo3+
HLtZ6fWSbYQ7sJt1nv8mPVu0fWA3P4GtWFYpD/CC7zue+rj+R+ORCsF3rPpricQsaOSrFrWk
yYhftKL8xRfGa3NsXLJpV4PH0Zqm60UrpMSlzptl4wpPXYeTAEv2c7JI57WzctHHk/bjHptQ
bDFwClRBKiTNkxZ5/J07prxN02H/6jx0Hiha0oFxlZ/zhZ/kNB10jaemguivUFrnvRr1/rrO
2+/xB5Scyx/gzWWUGkeIySrKA7u9lOcfseSB6AHeK/A6x2FDcpDgAG+WeFJqS0aEDfBmkcfF
F96syHuCVxTzTj0sfOkdwRB8L7RDgbSCuYpI90L4NQvIiJ53yM+RwRh6URIRI7BkLERctOLA
1s4P0WbZiCvWqsy+RZCktS4uyZircJH1zCMV4habUGuqUqtYa0TJHRwsedRCVf7sUbtNh1kQ
mLEJdciyWSTxzl2GptmAcqVHonCzZHvrS+J9Z5c/jtbxbCnvCd67xpIUaNk+lQO8Wet1XzuS
wwQDvPUuM3B8p3J/4QDvvcsNCnAywnyANz+HVsKwLPkcPsErCnp8Pg7JIxiC74V2KMZgpzCT
WfY3XyOPrkI75thEaEcYUxMagGaHjtaEdvRT6fo+zabFVKchNOmctECOixboiXphtMIjFuIW
G5dt1dQleEcEheQyA2sMqqld7Csm6XAc2KL1uEGW7ARdFdpxGm34Pk+HfDkXAu7Qe/K0LK76
HdXepxj9YfJHxRWnj9/a6o+SX+4B3lznwYJZk7UB3qxBzXdh2RmRA7z1LiPEnesta/9yoLf+
ii4kCiZXqQO79e8jqQUgqdgGeMGH5WpChEdyBd9JEwizP/+3+qKjFYhzdZO4aEXB8cLsb44N
lerKQNhfeyGWHBu/aIkG7edJD3NsaiGRDrU9alrJQ+U62bR/w+yPR27FLTb+MXap5rqtOiVM
ppMuMvujdlFvnGIT5i/gyx8ZUiOknWZ/URP82aN2mw71SBWhhw9UtlE1rvodJejfyOxPSwfI
LbQDvPnsEQpkNekA71V8wsW3b3m/vwBvVnyuhMmS4SIf6L2Kz7C0ms0/OcB7NV+rRbLV5QFe
ofkuDP94ZFjwnWCBVhp2Rm3id5k0txK3RQMjF4Z/c2zCu0+aCwpQ1XQfhe8MVzQSXhj+zbGJ
iMnIbvVtYaS4pg2el0wFX2m+EWFxi83D4Lk36/7NQ0ieHa0yeL4w/Jtj8zD8a+IvJKI1SR+Z
L+nyhNPjh/dpOmRs3WqP7VJLKvKXwfO3Nvzz1T1rB3egtx8yJztrntDtUk8t+wMe4M33WH1p
o6Si/0Bv/RUFuaAkhwcHeLPUC7fGpMf4AK9oJ7ww/eORF8H3sjzMt/SowgCEybaoDaZ/c2zC
9A9F4tNkkHWqjotW1FxOx0/fJ9lEpQ7IhGu0rWUd7ReV9y4MYHjERdxiA8V6t6b+NWH///QR
8xLXP+zn+dSzdFipV1d70Fzl513/lhwxw3mW3Cwd8o+LvzvNN2D+DqVd/6ak60vr/Uquf5Y1
/vpA75V8Uot/B5OfvwO8V/a1mJzOWlEc4N33Odqv0rLvQO+VfTXCq5K/4gDvlX3qjz9jNtLj
CV4h+05NXn0xHrERfC/SQ6H5hx4ebV/JDYtftKDucn2qO8Um0ti6YofIvM7GRsRR8GdX+KbY
PCp8ZP4vDj+2dNfnmgrflewbqRG32ISAowjz4AatYtoob5HsO7s5b9N0Yq62ViHfGoer0lbf
P74YS5+kQ87HhHz7B+lDqpfZ87f0/etFskEKT+xemYe1xI4qPSkc4M2te64tKSmhntitdzhC
xHw/mvX8e4I3V28tqgDpyQxb0fp46xnshbOtwAO8ROBdtO2NwAi+FxgRWgjs0QPfsu42S8YT
rr1gptiErYvv7EAY1ZK5qausYPiim3+STKg6MTNgfwOT02hrUmCvLP94xEXcYvO0/Ovhgky+
k0iOXW2w/Julw6Ti357oeG01WUJeY/lX8bST432aDlmPeSvsfouyJYqX5d83t/yDpIXRAG8W
AVgAk304A7xZ6GlEc2TnhJ/gzVJPi9XkXR7gzX2ZERORnQY/wHv/wsr+dUz2EjyxS6TemZ7w
FXjkRPC9nIjozbGI1NKKyVnHZbZ/FwvwFJuw/WN91FeEOW2i0pZkeOhFC9UkG9cS0CGOb13k
ZwNtZUlu25XB5EiJuMUmVJs08l1jB6ycjgb7fNu/STrM2mpzfUS9QzKpc4cnzCwdULAIPHTR
p5COJHl5wvx1rbff9o8paRMywJsrKVQMk+XGAd5ezUue2AZys7yL0lJyLz3Am+VdLdkuwgO7
Wdz5spNsyjmwS8TdRYP8yIfgm9kdDePIFLFpcogwrllxTgsX2m6KDIZ3oXUgX6UqJY8CcY15
oavj8/V2ko1/WUUY2aBL8tQ5LvpsbTfCIW6xeVg6V+psrftOJ+sZvEbaXZXxJtm4BmKwsOZB
10NpLfTZyR3TdADQ3xttzKR5g+pXGW+BtPsquz+pkmyGOsCby3iRdZF8FAd4s8LrpUnyLxzg
vTrPsFjW1HGANzdfkn9Fki1vA7y9nKyc7FwZ4CVa73zsVkZGhNzL72jUGmujyGfKNryWFcmC
l2Jvjk3oNm6+BPvqa5SMiFgk9pTPm/Jm2Yh0I1SkLpT1Rior3tZa6adP2o97bMKl2WUeWERn
A6UnO1f0f1bA8/aAWToszamoxIktJW19wiRwAR3Gc7U3TQfVUKX6goRZJ1O/akoAfLXa26fl
/uff//r3//37X//9z38gwD/+87/+959bF6rc93z35EJyZmHBR3mBFv8S08OqBbN2tQO8VwGB
/0cleSsHeLMSN5cpyXrPE7v1HkevISeLaw/o1l+PuxXMWn0M8Na/kHwDaj3bjnCAF3xSEM/j
VWRkeMi9DI8G4PsYIyZMzl7ENSvO0i/GoefIUPEtd2vaWaOyl9xmlrrkLJ3OR1Tn2NRCWtFq
lxalhPQ49IqB23oa0vbxoP24xwZKlV7VrEVIkCZPyvyqJTsKOZ+LmaUj1eU39IgjAU4OlK6x
O/QdxXltf5YOheOpb478/qgkl66X3eF3tzuskY+btTs8wNvP1ZPn/k/oXp3nS3vLhoMM8F6l
x1os3Xx6gLf+hgKPobxkA+8B3qv2Wi+abCU/sJ+t9UaEh9yM8ABCX397bZCN0F4k9q6GoOfY
xBC0hI2Pipkke/MWDUHbRTPbHJuY7mcmUSSsqNmm1hXGD7XS+eG6jACPW2xCtjUTMDB/3rRn
660rlHgluqi3TtIR6uqMWLU3TsYtLPM5PM9LnqVDUQcX4Gh/yMZQvk7Xv63PIQKG3VHyYHig
N+s8lx6ctbU+wJu1nvgWNq31nuC9Wk8imSQ5YDnAe7VeFf+KJNt4n9i9Sk+x9JqsLA/wkrP1
ixV4RGXIvXAJ32ooY3dtpJbsq8E1Z+uNzoZu3ybZUKijir1Br/Y4gMz5HC4ZiL6IMZljUx8+
w01beB1i8vS2TtoM/6mwdz6OJSMp4xYbV22ETAA1hrEwaWMKS6xqa4WLbcUkHRd50KAyNuuP
1saNhjcXPoezdMg/LmDE3eLVedkc7pZ6X2JziEAlm5I9wHv1XuUbziMHeHOrQHhQZGMSD/Be
vdd6sWQZ58DuVXsMxTRb2TvAe/VeN79tSdvkJ3aBoqh8ofZGSIbci5VoTar6iqXISNnRjCVD
xHyqXd8m2dAj8iOO18Sw546iaIkfINqFu+EcmepfLv+NwkVWELNJnZNDqn8q7J3bp8uIyLjF
xmUbk98WdW2EAslDaVhSda2PfMnrJ+02HX/QQuqhvzxoPe1+s0KKP4xVr5+123RIavcbhFIh
HEJf7obb1N5ud0PppYtl52We4L36yax00+Qp0wHe3KVXi68wWdubJ3ivjm8WAyZJCfrA7lXx
HEfu2YrjAd68z4i29+T8wgAvOb29qLOMdAy5k1iABXsHv8scibGaNQVcEuvWrqZlJtkoqCn5
/7Bz8juGawy59bQ++T7NRrhhzHiTNWvZQe8lo9H1VLJ+PGk/7rFxQQCE0XlYfcsoyXp9XLXi
9PYiD3GWTpyrd+7WTbAmn7VFFodXKXXTd8c4DNN9t6y1pW1vXil1K0Tel8xGN/D9PSePzQ7w
3lUWWpTNkzrgAG/WelqSdiJP6F6dp600aEkleoD33mGB0iE5mjfAm5WeFm3Jw7QndsXJbbto
lB9xGHInoiAkW/fNuwsjaZA8Tgtb0xW1vH5RYZlko+HFC6bhy519whdNRV/pvEk2wuK7aVeu
0rMZaKsscE7NGj+etB/32LgmQDbjLjVyfNMRaGuGos/dDWfZMCuRcnfxqk5rp7shn2733ufp
+BeUw0UztqTJHezL3fA7uhu6ZEvPOw7wZn2HBSSbqnCAt9fy0oe1T+z2Sh7VfCXPsZsreTVO
N5N3+ABvr+RVyo5BHuAllbyL+soIxJB7gRgYgbDEGuY36XiPJZW8S9+bSTYxNshh4dFunD1/
vsKbZCOs7AqiI7kK31zJu5j4GXEYt9hETa7WTuzao1HW/H1RJQ+uhm4n6TBV681ADbGmC5O8
otWQTjsn3+fvjvmDFj2gbD0drfcq5K1QeF9TyKMCWRfrJ3azzLPSk4FvB3azyOslvB3SBocB
3lzIs2LJadsDu7mMF2ewyVLyAO/9Cym+cMlP+wCvKOTpRa/UyMKQe1kYFbr57xdRsDXbZlBW
CP/rQt4kGwWirmCuWhGyovXzZd4kG5d5PQJtsQMlx22XFfIu2j9HEsYtNlGTM7GqVrGJpNvY
VuzgKtqFzJukwwIuXBEqt9rSQwufnlMyTQcsKpLkKhxq3q3xt6zkUVrn3Vg0kucKS6bblk2G
7Lb1a8WoZq1enuC9Kz9qyQ7DPaCbtaeVljbNOMBb73AlLijJUc8B3vobcvc9jSY3GAO89S8k
3zRAyy04B3aF9jzVN64IRlaH3MzqaMw9XF6QW7IRfI1987XVyxQbKrWGy4svodIlWTClJROm
2PuF3fEUmzh88DfPwEUbJ/s4/Zol47JXteyR1HGLTNj61YY1+jiFW3LkMK5a0it4MWg+SUcq
otTew6mrJdtJYE2AIcDF8NEkHVJh37GRWGuYXL1etn7f3tbPirWkEhjgzVUeKlY5q1We4L16
LzJmNHkoP8Cb9Z6WcKVK/oZP8Ga95z9Ltrl/gPfqPZGSTcs6sEtqjed6r424jnYzroN6FxMG
iWJDVu+t2BDzRcf+HBsqSNx8k1dd8CUfn7hmRanxwlp3jkwtNUo/LpPMJV9yNqSuOYKteJ6k
0kZWxy02odz8Swe9YRfMTx8ssXG+0nuzdFzvAQOyS2N1alv13s+ftdt0qNcKlZW6a3LLyteX
3lul9zY7+4FZ4XRVaqA3S71aLHvqPcCbpZ745zY5vTLAe6UeSwm7hWR33hO89TcU9AXYJVyu
t+EAb5Z6VjDrODTAS8Teed9+G8EQ7V5mx2OcUaWpy/rkTI5ftILNVWjHHBvy14mhVzDttbWk
Gc8SfYTK535rc2xcuGGtriKxN5f56dCOJXYv9YzNx5P24x4b1221mmLsHCvWZOU+rlpxsNzP
fZxn6XCLd0YMoXPN272ssKXG06z092k65C9MTEzTw4wnfew/tVF6qb1fx9zP95Q9aSX1gd4r
+riX2CUmBcsTvFf0NYwkieTieYD3ij4JI7RkEsATu1nyWbGelM0DvFfyNSuPQcOMonhiVwi+
ft7G30Y4RLsX3CEKqLUbV4Jk9HNc9MmnuXNs4jQ33PDCKkWy8pWWaApUOLfjmGMTH1fFMJAj
6JCtxpf62WbObURD3GIT0s06UaMerjyQLSAtMXPGflHem6TDiuofRiH2e5/cXCwSfP5L/uxZ
u02HfBVSIajGzdKhcy/Bt2BiZL+/n7/eeX+/AG9u18MSTunJhr0neHPLXi0Nsy7YB3ivlG+t
qCRTTwZ4c/XWSk+q5AO7+SnsBSg7s3SAFwgJbOedVG2kQrR7iR3YrFYEMt+zpX1fcImH81Wp
ZZJN62joq2+4VyRP2OOiBWzswlh3lo24yvO7I2qUdUHCNWGv9aI5tI1MiFtsXK75VgxNOtTW
q6Rtgpf4+53aFb5N0+Fqvrb4HriZ1aTL16KpYDjdHr1P0yHzPR6HXxIzJl+d11jwd/b3c3GU
HBo9sHvX2NpLVMyTzhtP8Galp/51Sjs5P8F7lZ7GcpCcC16zctwq1zbfQGTd/Q7w5meQCkNW
5x3gFcW8Cx/nNgIh2r2sDozRjAjiVZJkA1VctOT09qKYN8mmKbqQiHIem25NHtF6sfZOshHf
ZXFVVpb0vmxNNxheNYWOOIhbbEKxiT9iriI6hfPxVoO/etEoMEmHqVNFFvL7Y0kTg0U+zq6W
f/as3b87EaNCrarTackZ9FcK73c0+BMr/m1MnpQd4M1llFp6T4bbDvD2Yh72bFnkAG8v5rWs
x/QTu72Up8nT0AO7+RnU0jnbMnWAV5TyTmOlfOEdcRDtZlSHRlpVMyN9qJSNpbxTGfE2zab1
BlGHkubrVJbNEntt5XPTtVk2QtEiD1Y7aTbOe0Mpb4RB3GITpTwVDY9twDjp3Grwhxe7iUk6
XJ97CajJXuJldbxz25dZLtQNIhdZgChr7v+q431vez+CbN7pAd4sAaRAfuz2Cd4s87oLj+S7
P8CbK3lckolnT+j2xkuU5DM4wJsreVJaujP+AH+2zBtpEO1mUodiQ6ikXR9r+06Zd7H2TrJp
rvO4Rp+/ZQc7d1TyJtmIv30GqiwImvZxXuPjcTF1O8IgbrEJwWbkr6qJP20t3Za3ppInF5W8
STrMIOR7CX+/e3b+fk0lD81++qzdpwPQKJK3KzGnz59/y0Lep/j7Zcf21kzsLRsP2e/w1ylp
lzDAm5d+KJp82w/sZvFpj7T2tMdfgLfe45iP7slBrwO79RcM076aLKoc2K1/H3GL3yR3jDzA
K46Rryo/I6ii3QyqkN6aidTmuiA5DPb5Dn9zbMKsj6P1UbQ2TA8BL3H404tghzk24fCHfolI
67VlQ3XW2DFfWfy1EVNxi01YvqA/ZB2Ue892LGyw+JulIxXJH+Fq0NAkO9P86RZ/s3RI2e8O
+i/la2bSmB0mE05/dfX5N7L460WyXeIDvLkSBQUwXYl6gvfKPeFSk5lIB3az2JNimJzzHuC9
cs98DZbkqdMA7xV8MRht2SHTA7ykb/A8F7iNyIp2M7LCV6yYzqy+CHO2027FweW1xd8UGypo
LUzkkMPROfcE0ZqU435aO32fZBPzvMC1alNQyobXLBoCvvL4G4EVt9iEdGOI03423+Em582X
Cb7z5JpZOkLhXaMxj0SSTtJdcuR/6fE3SYc6NHi48igk99ovi79vbfEH2JIF0IHefqwcG960
UAnwdqkX83tprRfgvWKPyTV6egTjCd76GwqGk0Cyj2WAN4u9Vrol16sBXnG03C4s/kZGRLuZ
36EuIZsSVc3acCxyfLm0+Jti47rNmmHtRsLZtLUdFn9TbMKbOdJVxKw1Sk5VrLL4o58+aT/u
sQnHF3SpR+jKC1raRG6JxR+cFivfpulwYxKt/t6I08pqV17hTw18MSQySYdq5FFbb761MEsP
A0/dnZfa+5Us/jib4PGB3iv6pJaWnsg8wHtFX0NfeJKtP0/sXsknULLplgd2s+Cz4gtC3uAv
wHsFX5Piy1ayuneAVwg+OD/O1ZESoTcDPISsmq/CIPmp4BWBtJfHuXNswq0PjV3/UyOm9HHu
Gou/8+reHJta4nxNLQacO3La4m+JidzpjMXHk/bjHpuQbkquXiO+AzB/nPvZFn+zdFiROkX5
1bgl6ySLLP4AzqdGZukQIUNkhlNHTFvzvBz+/vrQyG6HPyuYLqcc4L0KD2u+aDbAmxv2XFZK
tvP+AO9V8q0V1GSTyQBvLt5azEonz+kP8ObnUAtT9i88wEvOcM+9X3SkQ+i95A5s3LsSgPRs
Ftgq75d+XtabZdO0+bYTw+JPss/4Go+/fpqq8j7NRipHqFmNgZHk07ZoYuRqMFhHNsQtNo/B
4Gg3a901eD6X99MHg2fpcFV9mBViD/+kX2U2eJYO9d5bt5iAsd5fHn87Zd7XzAZD0WSc9IHd
rAKwQDZaYIA3az0tlO01G+C9Wk/9vmWnqwd4c80WSrK5/gnd+9fVG37dA7zk+Pbs++6r7wiF
0HuBHSi9ASn5mgXZEOlVOu+8gWqWjQL08Cozcn2UZaNLjm8vJoNn2YS+U2VDMkwqibhoRfnr
wuNPRyTELTah2Ji5icY5oaRNUxbpvDMR/jZNx7n4c9ar3/gY0MjqvBWth8BnPbvv83fHmvl+
L9wXNX16+3tOBv/2Fn+9Zs/KDvDmKgqV3pL1xgHeXs3Dnux1emK31/KAswr0AG+v5UHNKqgD
vL2WV7Mj4E/sEoV3PhSpIxFC76Z1qDZhih5CyJ3TbEjrmGXTOoKYYqtGWTKfHtYxS0aqqgFr
A0n30Cxy+OPz7D8dcRC32EQhr0WrIbRK/o9ZRfT5hbxJOlybKSi6MPIHOX1c++mFvEk61Dtw
NDI2zRdZX2W8Bfruqyz+GmDuJRzgzRJAIyUwKfMO8GaZ10traZeVJ3hzIY8K1eRQ4gBvL+Rh
zYr5A7y5mMelc9LzfIA/W+qNUAi9G9ghVqFpw3TDxg6pN8kmTtEqoxpC9kRikda7LOZNshGs
bMSGVl1L7izmXdn86YiEuMUmVJsKhUF1D1PJtJ5YY/N3UTeepMO+PQJwFenLICSNDDYEdkzf
HfPNHph/BqLm+rcu5tXPsPlLOiVtDrpNqr0lhzcLhPHXWA+Gjkx2AA3wXjkCrYSBVU6OHODN
sjiKwpp82A7w1rtcrRWj5OswwFt/Q7YwjUz70TzBW/9CiqjulpTFA7yil/FUSLpYGUEaei9I
wzr2iqrkgjLtfm0rhOTViPIcGyrVlVeNir0JJf3d/aIlsrhf9DJOsakuVbCiSxVBkqTFVZ2s
S/2pyHaxARtJGrfYxDgroD3NyVWSMZqzQ7B/rOjK+YjyLB2p4dQVdtHgdyc747HGjwbOzS6n
705vxL4YSa2mSQeLVxH0NzAg9G1qVvI9wdsPvKUnBdUA75V8wqW1ZPLzAG+9y4S9ACc9xQd4
628oQIUl6Q8/wHsln/qNyzo0D/AKyScXo6MjVEPvBB3UAtJIlYFF0kl9BdZEF19Ivik24UYp
WEOwiCbLun7NCjL9dN7jffrWuDiS2loMSJBmLadX9B+j2YXiG4kat9i4OuDqAglqQ/YHLj0f
saJySKdtgG/TdIQrdcDuEkksubuIq5bcnZ8+a7fpRLi6AD4q1TV5hvC7VkL/JhaE3LMnXwO9
va+sW/a7d4A3iz0pmC3vPbF7pV6NdIjkMvjE7hV6VYtScrpmgDcLPS2YdWQd4CW1vfNkOx0B
FnovwAIimouYMV3ai2sWkGmn0uhtkgxFPFfXqIQRQc2VW2hytfpTd+NFuWXy1jABCkqzTkBZ
98El/XP1VBl9PGg/7rGJ7sbKTdk3tmCQVkZLnLMfMaPXj9ptOqyutyordpRsJ61ftWBH6vuY
c6vpWTr+CTU1/woYUdbgd1aGv4Ter+M+SPnD0g/09vYyrsn5sAHe3DaA+b9wgPcqPm6l5vKC
ntC9eo+lQM99QQ/sXrVnLjEtOds7wEvU3oUrzUiv0HvpFcjySC9tzNnAnoIrBnNYzzry3ybJ
UCH1Vc5XYEweFNJkNsIfT3HpTE28T9+X8DJuLieAe/KUoK5xMsZTe52Ph+zHPTLRpUgKEiov
ega29jbW01PPt2k6bNSxm7/Z3ZqmQ39XCFc+nbt+n787Dah3VbVmadfsOUPfl9D7UtvBXvw+
J8soB3ivcDIr3bKJpgd4c6teLS3tRPPA7hXwXf22Zeu1B3ivfOeId0iatQ7w5g2GK3LLmg4e
4AUyAk/DyXzlHXkVei9LhFBrqxSOsjUp+HFJ9xS20xmJt2k2LiKcB2jn1tKmg7pARvhqf2EQ
MslGpPYWCTLILVmbXGP7XStdzCqPtIpbbB6RPy4duQkac/LlWXVsexrC8zZNh8NDDH1vRFIh
3ai3ZH7l0oxm9u5Yi+8okLGvma9T240a72uGlf1LAblN8IHdu8RCi/9mfiYjwJuFnkZ3a1bp
PcF7pZ7r32rJNf2J3XuPBYsl+wcP7GaZZyU+h0mZ9wSvkHl0XsXrI6Wi30sQ8UWqxvyof+Kx
ZoXREn+dK5k3y0bBlNSJkCQtKzeovFkyIo1RW++sWZPV6LBYoiN++qD9uMfGdYTEyHXvgMQ1
n1ExnrT/BwAA///sXcuOJDmO/KIRJJKSyB9IYDO/YjCnPez0Yff/sWSEKw89cC9ztVJZVR3o
QWMO5p3BkMJl4sPsqyQHZ8MR0e6/mMdoSctoYnKN5CCdK9JMh5O1cs/a4z0AKlP5U1M/nRfN
+07NwRYXLnCWcIA3M7ySMmqY9MRuT+Qx+gEHeHMqzzmbguMNA7w9lUcCyvkM8PZUHmf0Ex7g
JZXa8754HR4Ves+jgv2zkVCVarjcyZw71B2ONxmNczyPx291Fd1AOzjeZDA1pkmi7sxVK+zY
vITj5fMGUB0GFbeiibOiq/93m1pWqTDHW5L6uhi5nQ1HWGIaOnirk1ZYiWaN6uB5tXZ6dUzM
LxTO9IQzWMx7jdz+yrqD5C8+sNoxwJupniUT1CzuAG8me5r8xYyaxT3BW1eZMiczWKTmCd6c
zhP/o+DU9wDv/YRMya+/qJHNE7yC7NEF2RtGFXrPqMJv8WxWOZM1QhkFL5nCuCJ7k9H04lyv
qOQGv8kWsb1+KknyMR2Nv2QLNafi1PG1WcT2zuu2OmwqbkUTjVxUiZ2N+5braGVwhZ27k73z
1rzZaKRyqb7JnPQRgS6LqxJ69SKhNxtOvFyohPpNUbCe97sm9PgrdAfBAt+K0t6vrPBXjHGF
vwDvPfhLTw1UCjiwm+mnpU5oJu8A76WfyqkbKutxgLd+h+J/lFH3zwHe+gnZ7w1GqGDOAV7w
WqGLhn0dNhp6z0ZDrYqJ9lDMKWgJ1laMzVY5952Yi4ZDf4o9oKxZwBuWP7MicWrlghJMBUOR
Bq65CDMHy0Hl/VZks64s7HR4aNyKJlSvW1b/qarvtw4uzqLJEG7n4+az4VQqXEyL/7QLwbnG
JUbSOZ8rrE+vTm/sv51sQr3C5fG5maqfnX7+jeT9LIVvOMj3nuDNiR5O0TQNJnqe4L2Mr0qq
Cn6HA7yX8VkoQ6A2Igd4M+OrvrXACscA72V81S87CqpiD/BXM75hpqH3zDTUSifzRS6igia1
Vrgwhn3W+Tk8FQ2nws4m/Cj2iCpYmPCHVlzyu5wVZD8mo3H2VnKtzcmkWu5YPZbWcKSrYWAd
Vhq3ognyJq2V8PltuYNphUWUr9hFxnEyHN9fVGsP6Rd4uHIN5SuPScnrvXZ/dVSYwiCohFsf
XPx/Ub5FlG9zj1nJOamC1P4Tvb2sh9qBH9jNXK+GdTku7xfgzVxP/agGP+EAb/0Oa+HU0MHv
Ad7L9VpOrYDF5QFe8I4/P7L8BB4OEXrTvSNMxsTCoutR7cWyeytOrCsp57lo+NGY24yqcwrp
sO7Lilxlp3OJv7lograZqhOVLoqKH9Miu4ty0Uo4/CFuRZMT9VKzL44zidIrqpSyQm6KyoV/
4mw4vtEaNao5xq1gjz5ZEk6/aGSYDMeJXu1E0ihE3ODa/1Qu+cX1fh6Jv9DlB1NTB3gv4YsG
PFBA88DuJXytJFJw+GaAt64xZ0uKdloN8F7CRzn1ihK+A7yX8PUSKs0g4TvAX034hkGE3hHt
D+6WtfUe6RaGO9aWEL7Lcu5UNI9ybqdoQGCSjEWzqJ7by7nO7lw0MVeW1Zl48AmrqHnHCvpK
dOrJ/LnT3u5F49RNS/iqxDBt85cKSvhWiCAXvajnToYjnSqZE6RuBRf6W8H3zgd7PqajYW6d
nee30rLCdO+l6PzXJ0f2C/3VBqbWB3hzx15JHffseII39+xRalJvKP3JCs+eW/PBlGpFLaoP
8GYin1MG75UHdvMu1Bj4RXfhE7yARnA7q9v4wTusIfSOXL/fMfwXUjXXzkYNFfpb4mErV4mW
yWiaknKPYWxRWBpvxTW19FPRlI/paCrnUKYmYc1gj21Z4/l6njX63Glv96KJrJGvTgyj92YZ
dIiZzRr9uWXvdNLqfTqcsLlohVqjYgSKzi8bD75o2ZtdHfOLRMuS6bn4r+ngbRzvu4T+ioJt
8QO895Cl6HQHc1EDvJnq9cQgCziwm4mefymGfsADvJno1aSCyjke4M27kJOBBuUH9quJ3jCG
0Dtq/cHZyKKFqhY10OZiFdE71ad+n46m+QMtetdLU1SMKbUVc8562tr2MR1NpRzzmtlUUHHT
sqr7/6J4O3whbkXzTBd18iuP5WaKZr/W6MDQRZ/AZDjBvrv/ZJhKxWu3K6IpdhbNx/zimBM9
D8hjiTvfS9F5H9HbLPVXLTREwVzeA7s5iUJJVcGz/wBvT+XF5Q5O5QV4M8NjPwlBFj/Am5sw
LVkGP+EAb0/mlQ5WlAd4Cce7SLEMZwi95wxBVqT0HqpyYEdbWeKLWuR0xPN9Opim/g+3qlwJ
NZZMbUU0l7m8yWjCFcJpRKEHC9+Zy3s4/l5vtLd70UQuT4mJVUh6xeWcl4RTLm4Tk+EIaZfs
70YOqwtY/eXLc3mzq6N+k6+1V/MrBdjp8Erm/dpSf4q25g3wZhpQUyaw9W2AN5M9DW1ZWOnP
sXupnkWPN1g2GeDNybwe48hgLu+B3ZzKazFDiObynuAvJno2zCHsnjmEkwgiYuZac0fTX2uY
np27KcxG47cSy1St5pxRsc20YtLoMpk3G031S0I1eRjXgo15a5J5xeyHO+3tXjSRlis9i1Lz
kApMjZYk84qddU2+T4cjHEUO32lVrYPn0TJ7tvPOvOlwMhVfH/alzwyXbX/PbN6X6PwVVH1t
SaVk2YTIbqW/qMyBegkDvPnsz6nDZbwHdjP7NL+1oXmBA7x1jUlLKmiqcYC3focP8T50JH2A
t35CdtYraMfAAC94rRQ+LyfbsK6we9YVj2FT34nFjzWwjBQPLYjmajRkLpqY8qhOBYVZaoZ1
X2iF7ovqef5nLpoY663drFqvkkFXvw1SfzaMK25FE1J/3LSGh02Bff3ymkmXK92X2XBiBNi6
E+rSWcFi/zKpv/NZ4OnV6dVvbo1Uul/j4PvBS/dlFdP7Lqm/3sFUygBvTkbllNGU6ADvpXxV
/J0Lqmg8sZsJn6aCOqA9sXvpnnGqoFflgd1L9mLNCMyHDvACQuGb+fwIHs4Vds+5QlvTbFS4
E+Nkb0W33ZXI31w0nIrFUHhhpZ5Bqwcne0uEXy7mgOeioURWVbK22gStr6waAz7rTvvcaG/3
ggnWZuqEght3qQaziTWyzmfpuffpcCrn3mvJTTpluBNyTdX/x1vt/upoyX7hi4lpQYV+X1zv
l9X4y2ahmQAmpQZ6e10Znlca4O00z98BYB3oAO8lelbDYBdV+XuCt36H/gZNHaTKB3Yz1eup
drBSMMAr8np23rxvwybC7jl4WI72way5soAnlj+0wnLtSuNvLhpnbWZas9OJ5psWpXprNP6u
qn1T0Tz0nKmHR4Q2A6fj13AjOg3mc6O93QsmJ2pa1VdHizNJ2yrx9zD2vt5pt8ORJi0UJWOG
VsBu4nhqSWH5fExkNhx+6Ndw8x3XGM5SviT+llG9b5L4K6nD9hMDvZfxVUrN0C6uA7yX8YVy
XwUF4AZ46zpz5qRoL+EA72V85K96Bld5gPdyvtZSSHOAus5P8BLOd9HjNXwi7KaHh0q2Wmvn
mBH+aWq5U9GEzF+L3JSVnFGfmlUyfxdWWnPRkBMethLWYIV7BcsZa1gS8Zk+z+dOe7sXTdC3
2p0p1VJiHB2lFV8u8zcbjnQqnSmUGMOieq/O37mHx2w4HA4e3VquYgUcIHuRvl9U6K9RBtVf
DvBemhcDv+AHPLCbG/YovGzh0WDH7qXyWlJVNO14gDenbs2Z743J4ABv3oM9tQam9QZ4Sbve
+cCmDXsIu2fdQb04K1K/abSMy/wtqeDqRVpvMprWnTiKOJOA7RQWyfzZqfbxx3Q0lSQq0aIx
Z4FW19c0hJ1mjj532tu9aB6Zo9xyNpFeUZeYDaPBs+FIENUanYcxTQvn9b56NHh6ddSasP8m
TdHj6zUZ/GvL/Pk1GFb5c+xmEuB/s8OOvE/wZqLXkwhqdHeAN1O9nojAksMAb27GjNYAVLX7
AO/9hETJBONFB/arid6whbB7lh3UTJvGDV4znMtbQ/QuNGBmowml4FbIuUSw160aMFdEbzKa
Wqj4XYuZSwcdAeOhJb16P9xpb/eiCcrGXbJGKJVAeepVRK9e9OpNhuPXCYo4qCsXMNO6Qedv
enXMF8dXppmp4bKFv+Vk8G+v82cGqtQN8OY8CidVsCA6wNuzef5SASnUAd5M8ih1VLxkgPfn
8zJqFnyAt+fzKqOO0Ad4AZW4UnO2YQ1hN207NO7wrK0ZngH7ctuO2WiaBjHyy2e30tAM2Jfb
dsxGU/1+5atSfHUYbqH8ctsOG8YQt6J52HZQryH3V0sBtYZ25PMmw5GwFq4UkxlqjNY4F+Xz
Lkq2s6ujKvK47sXMN1yyfSX0FtC870noceoZnCoc4M08oCcWVGvlAG9me+r0CG3QO8B72Z7F
LxsVvT3Am1N6PZkymtJ7gjen9GpCycSB/WquN9wh7K5zRyaR3EwyqsC2iutdif1NRtOieBsS
eY0YzLgucu64TOlNRlOLFM65VH+Twa4qS1J6V84dNswhbkUTrK0/UnpFcKL35Up/k7E8lP7Y
WXijhtZvduTzZpfGTPxnY/Ee6HBv3u+Zz6NfXunv1jgBOEiw4A25gBZ/j/5gS6BYwBO6l4jk
Fr5lIFU6wJsJsSVUzefA7qXDmSVlVHHgE731O3Sq5BsLrMIP8NZP6HcE/6PgLN8AL6HEZ7TL
icpw07A7Dgf+E861+e3WqrNJUK+vbZhSnoqGnXap5taddOUKFlJ5CfEqyheUeCoaSjVyn85U
nKeAwcQzK4rc+aLIPaw0bgVTUim1VmVu0k3Ru9cK0U7i0/Gb98loQlnGuPpNvGV6aIJicjQr
KLGcpnI/pqMRv0RS607x+x0t76nF+dkp8d9KejAXcK5vgLeXuyuqQzzAe/leyMyg1soDvJnx
VV+5Cv6oP9Fbv8UYO26oweITu5eRMqfQCsEY6QFewCnoNM32Xz0fnhrxf+7wPY1pAu1USCpY
Uo2HlvC9s4Tu+2Q0Tt1azaQl2guqYlOj/tCSFGg7IxUfk9E8Ru9qTCj31hlt//CHVhA+Pive
f+60t3vROHdjczIRLdJSYWPpFdKn9JBZud5pN6Nx7taycFdzMt4eo0sY41uhSlNO+0Q+psOR
1nPMsGlpJAL3aE79cl6M79sFCEvOyV8r4K9woLf3lKmCd6kB3kz2anBgVIDwCd5M9qympqiN
8UDvJXvSnQWjgjQHeDvdy6hkzgAvSe+dWj70XAaluGMq0FNuWoyc73URwwiSP7SCINXTfsD3
yWj8fsdh1Ed+h8qothYv6Qe8pntT0YSSAUvvvkIKTyvHQysYRT4VpBnRvN2LJiezSsrVuasQ
K9p6mpeYi5wPxk+HI9YrS8slO0EC3/nO91aEw3TaSTsdDpv/cNivFqV3tD776m789VUI/bZb
UcYy0Juby8S3Gewl+wRvbhsoSdBq0gBvXueiiQvYy/qJ3kv7epiwgTpJT+xe0qc9DmSw6nyA
v7am2zMNYnHHXaAlo8bipLQYk2ANTv7QCpp0SfqmonH+1luYMyv5eQyKNUclYAXps9NS23Q0
YTPbpPoZ3xs4QBUPrWhz5FOJmhHN271onL6FnEvWHJ4pFS3qrrAPokfR5Xqn3YwmrOGYxVeG
yCnlZkO5etroOB2OCGUzlSxNcbu/uXTAi/N9swihFLB7Z4D3cqho04INUA7w5s49Sg1VKxjg
ravMvUaFCEx7HOC9XF6cRoAJ3Ad0802j++UBVcI8wCsY3ml2ws9dHizinn+FM6KslQujd3l/
ZEUs9aqGOxVLSZ2DEImUkNlB80Z9BVs1Oku4fkxHU2O4oAlJzhnUMS6LmvZOuffnPnu7F00O
qXWLGqFT4YL2kOQlM0YXjOh9OhxfGr9FmHS1XDJaxF0yyfKwj77ea/fDyWGGp01JO5yilCn2
/eJ3P4MEYU7R3gxOLD/Be4/Y3Py6jsrTHeDNNK8nQduPn9i9JE/ZTwNQ0myA966x3x/UUKHJ
A7yZhsaYKzh3OcBLiN7pxHLPMujEPdOK0P+l8JEzZ0ggdfWHFkTTzq29JqNx1lb99PX/cLEQ
2kCp3oq1sVPZvo/paJoveH0YuDZieP56yVhsO1WnGdG83YvGSZtyyDLn0KhBDQ3yEukg4lNu
9D4djsT93ClrUcroibTKRa5c1G9nw2Enelab5Yev85eK7by43neLEKJmDgO8meSVVNA81ABv
z+VxueEpEuCtqywUFzEs2XFg965x2KwxOnR4gDeTvGhuQ2eDDvACIkGnc55+9NZBJO5YCVD8
hLMIP/qmUGK9ZPa+1NO+//fJaErSzmGOEjMZBaw6xUNLSN6pU/B0NB6M1ZI9loK21aYVClJE
5UzJ5XOjvd0LJjv/zpFkrU7utYE6CvHUknTe6RDudDjSIzEpGtk8AlPH/tQKynpZr50NRwqF
yU8LyYUKe+C96rULON735PModUX1pg/wZqrn/DKDef8B3kz1NExXUcWVJ3gv1dPw1AXT8wO8
9TvkLIkbmC8b4L37UJu/tlHd8wO8guzJRZ98G4Tijp1AmOrW6q93CzE18CK/yFT3oalzdgRP
RUMpeCsJO6toBUyrx0MLotHTbOvHZDQlmS+4+XssPwz+QLa34p1M+epa0QafuGdcoc7ui1Tq
2eMBVb3iqRUZPT6VIZwOp4aeovna5NIq2Ai6SHOF7WL6ZzYc32Ycnbrdfz9g71aeFLz82dke
f4UMIahssqQvZtmcyHfI/WF39AO799wvIXcMujIM8Gb+aamhzGSAt65xyeGni6qXfKK3fot+
6U3WwI7rAd7LkWuLdgqwLn+AVzDQ05SW84I+WM4dp4MWDtqNsuYYQACrsG2JzEippz6s75PR
ODWW1vwAda4eZn0on16RPLWrlq6paCixX08blxqMDVQoj4dW1JRPRVM+d9rbvWhKytY1+hKj
uxNuhixLBG2uxkOmoskPd+mqJpxLRi2u1oyHOO394Va7HQ5rzVmcTVs0OqPpxtdI8DKq912i
f62gjO+B3cv4Qj1NQOo+wHsZXxW/VIKDogO8mfFRj+EPkPA9wZv53mPCBxTUO8B7+V6PNjpU
Y+QAr+B7p4YHfgrr4BR3DA9aajXX3qj3mrmikn9tBUOS0+Hm98loOJUe+Z/aCweNBfleWVNe
PmNIH5PRUJLiNy4pWZuHg2rAzLXw3+F7OijFPQ+X4rTImVcXZgNz2yEMvYTvXXSrTkUTzK2H
XVAv0hk9M/MauSG7mjyfDEdy5E+p1VaLgDel39X35G8g+ZdNU1XUHH2gt5M9WLZkgDeTvZrI
wNLoAG9e5978eEMHlwd667dYi6XMYK/eAG+mezWhjssHdsFb/lL7xQahuOnnETtQqvNIooaS
vSXaL5f6zlPRhDVHzDpY104CNvEv8vOwctHgNRVN8DY/ebk2q7mDWgg06bJwR/DPBp+4Zxph
3ao9CpjZr2doAXNFZYGKng1uv0+H4/vLfzalW7R6glo2s4rI/8H2Li4Wk+GwOMnr7EvEflNC
w5n76bzY3s8j+CfxzoR1np/ovaQvmvBQdfsndi/la34lhQXrD/Bmyqch4AdKZRzgvYSPNErx
4BDTAd5L+EySNPDqMcBfXM8twzai3LP06JWp5cpOJ9GRnbakqf/Kwm0yGk5OJSQa8Mxvo2Ad
gNd4NKucU765aJy9Se+t5lZZOviL9YdWtOBdUb4yXCNuRRPkrfracCcKXzq0ZGgr1G2cZf5o
q90OR5zs5V79FWmscDgr5kec8v1wr90Oh6tvsd5avAZqgynf1GvtRfm+We+vdnB+a4A3N+6V
1A0VrDjAmxv3KDXwfDmwW9eYe4wKoDmPA7yZyPurvYIl0gHe+wkpp9zRXXiAV+T1LsZGyjCL
KPfMIppfNahLFqoZzE74Qyt6j6SfJ1vmoimpqZqfuJmkZnjQoi3gEcXPxvODdzKa6nfo3CT7
sYu6VZY1gwkk50XcMqwibkWT/U2npcdv1V/JFR2zWCP5dyqc8j4djXCY2mYjzgVt2ZuTTflz
MHKuODQbDBubU1XJuViFbYdfLXsrGN53Kf5ZB7vOB3jzEat+v0PFYA7wZqLXE4Ot1Ad2M9EL
x11wgmSANxO9dqMn8wBv34WFwG6wAV5AJsppl7kfv8MgotxR7Se/qzmRz63nGrYKINGrK8pQ
cmGjNRdNSCu2rF2p55bRXpQlonLFTkdQP6ajqaIcTZTO8lDBXX9oRTaPTnOTnzvt7V40wdlq
uM+RUljFoGrISxT/il1k8ybDEclUqHZhEeavtbv4Uzhyofg3HU5urbEvTfWowOm9l7rzL6r4
1wws3Azw5mweJYUzPQd4ezYPFS09sHtJnoqf0aBMzQBvJnk1aUHV5w7wZpInyRraN3WAV2Tz
TitPfvQOl4hyz7+jZ2GNWU8j9JcfDy2I5srBYy6akjpp1J89oALeBBcZeHS+yLFMBlOVcilO
jXptaBfIErs5Ku2HG+3tXjTB1nrJIWkjlUGN6rwk0UqZLm4Tk9EImzNHbaI5Kzi6vobiXU5k
TIeTi6+LdLFqGZZjfE1krKB435PO4xjwB7N5D+zeE5ZrODqi8xhP8Gaep0kZFCQc4K1rLFn8
/QlWgQZ47yr7FYI7KqZ3gLdXlguu7fwEr2B6ej6PUYZJRLln4OHfnXWi5jSyZywp4Q+tiKad
kqP3yWhC2Ziakz0uxgK2/K+RQy56yls/pqPxRanVd7hQJ3hctS0Zvs0XbaDDIuJWNDl2GlPm
Jk6NKpzOW7HVLg08ZsORlv0+YblJNymwV9saA4+L5rzZcOKHU6rE/xRs0P9dDTy+RO4PdcIs
S3qFl82J7Bb8q6k3MFE2wNt7tjoornRgNzNQS2HUAAv+BXjrGoegRDJUq+4TvfVbFJUkFdXE
fmC3fj6uUewDGegAL3itXI6HDAeLcsdWIOT+QlFOKMQfFGOg8dCKXOOF3N9cNCH3F8olpfTo
tcNYQTy0goHqRbJxKhpKXClc5DI93I9Rub8lfhx67hZchoHFrWhC7q9x94iyFoKdX75c7m8u
mpB/Yc6le1A5BLQ3yv05Ab3oXZgMh7t1LmRhvZhhf7+5s+tnJ6B/K7k/UrCMMcCbc46WDMyL
PKB72V6NyU+0DHSAN7M9otR7h9X+nui9bM+qU0zsEx7YvWyvEa7yM8Ar2N6F2F8ZFhbljq1A
S41CYqRaya0LLPa3ZE7kQuxvLhonbiFMFVXlLhmsk8dDK0rLF2J/c9E4cZMaUoy5NM5odnsN
27sS+yvDwOJWNEHcoqfTDwyuDRytWMT2mM9uSe+T0YRsH3dqzcKaB9X9XCP2R/n0mvQxHQ6r
aetUIsVtsDXea1JkFdvbLvZnqRBooPCJ3l5cJn9lwMXlAG8nexWUSjqwm1e5h+0rmuce6K3f
YS2cCoNUaoA3k72ahMFumwFeUVy+EPsrwy2i3HPyMMni61yd6xVQvyIeWkH2rpRfpqIJdU8j
js4uM387oWJ/S+wV+Nzfay4a520tXPHMGZ8w6mA0KcZxR/llmEXciiYGC1tRc+7aczMwi7xM
7O/cOXg2HGlNnbxG42rz68VGsb/nEXi9126H428o6c0qm68PKGoVT73Y3iK2901if5xyA3fv
J3pzrxk5TQIZywDvJX2tJFS99MBuJn1KCc3XD/BeykeSUD51YPcSvq6pP7xvoQHrJ/ira7nD
LqLcs/Lwt3vv2TpVJVBOzh9akQ+7JHxT0YQLW8nUSiUTEyyaRdZtl9m9qWgiu6fCzo4sk4CV
6VXZvSvCN9wibkUT1C1byc8WPCdKOwnfQxHoeqvdDse3LwtV9gUinL+ukKqgLBfF3Mlw2C+l
vVCv/uvhDHu3vdSd//rkyH6pv46OZQ7wXooXSZwM+k8M8OaWPUoN7TYb4K2rHAZiHbQ0P7Db
i/RdQBGCAd68C9WXDR0OPsArsnpXUn/DJqLcs4lo/l/tmSU64AmW+ltC8q5SLVPRhJhL7kJF
LEdD1U4FmC4XqhyT0VQO6WPV4rQINE4va6qEl1J/wyTiVjQh9edEWHJzatRxebxFWn8X3QKT
4Qg5ZbXmdwrRBspKLlP7u6jhTobDFq8X9ctE6QbKDb1quL+y2l9JGbVDG+DNPMD/qIC5ngHe
zPW6X3PQbrgDvJnraYLV/gK6d4VFEywCo0vG7W5KwLQK6/w9wQuYxJXOHw1nCLrnDFFbq9or
s9UMjhOt0vm7EHSeiyYIWwtRN9Ma3gM7BZ2tnAs6z0ZTSVp3GhFeF6BVUVnT+U/yw532di+a
4GuSrZJ17rWAnoCrWF49zxrPhiNC2h+TGRKdrj+LCMx0ODnicJLXq7YOZyZfIjB/neVt1vlr
2RkbmCgb4O2pPBUDj9cDvD2VVzrqx3uAt9M7AQsMB3YzwfMvJYO+IgO8meT5vQHUKjuwKxJ5
p5aifvAOXwi66dnRKJq/slm05qCJvBW154c4y9m5OxVNSU6INNw6jGsWVC1liWah2nl73mw0
tUqrUrqaoW6UG6ScaRhD3IrmIeWsTiLYLyqZCe1nWyLlfGXaMRuOMDFRVnX+yDgn+mrbjtlw
2KRZ7+YrX4vA1dpXIm8Bxfs+nT8wTTHAmxN5PQmBQ+0DvJnpRS0bZnpP8F6mZyUa8FEL2Sd4
e/clqjV1YDfvQkqEtl8P8BKud3ECD2sIumfb0dgJhSqLGqGOc2mFTco115uKJmhbzjFx64xP
cEnnFVyvn5Y5P6ajqY/ZBV+bbhkcLImHlnC986EfGsYQt6IJdebatJP/K1eG03krFse53rmk
5Gw4vr96i5l1/3fBdf6WaODQxb1iNpxCZLWEGrq/79HB21/TtmMfk/ufP/79x//98e///tc/
ir+Z8j/++b//2npSYa/A3ZML4NDCgrfyAir+HXKHjSRRBY/jAd6c7IouHJSjHeC926yWRB0d
QDnAe69bmVNHrZIHeOt3yA9lJfCm8MRu/XwW4/boBxzgBa8VOjXjdXo0/DvojqlCDASbdY2W
tpjtRKeIV7iR1HJBxKeiifqF0zw2KqYMZo5oSc9I6afXio/JaJp/MBKrvTTSDHa2tiXRUD6V
jPncaW/3oslJc7MYX8qNcgMPGX9qhX441bNb0vt0OJW6qN8scufOBa2rr1HA4fOZ6LlwShLT
mCyzVk1hqfr6KquvInrfkXhtnBNXcE5hgDeXXzlZA4dRB3gz32upCTpVfoA3873wJAHZXkD3
rrBSElB578Duvcr24mcQeHkc4K/mesPAg+6YKjwGiJXID6vSGeyhXDRALP0iEzYVjX/RmYuw
n1j+g0I7mP2hFQX2i3HouWhqqs3/Ib9uxbwfeDdb0t96zfWGfcetaILrOdvzneZ0r6HhLOJ6
l0nXyXBENHcKgUBxDgsX2JckXS98uefCKYmVM/sCacnoGFN5SVsv43p7665WgqeDTS4DvL3H
TloDq4AHeDPJc2ZZQD/iAd7cQxFHCEjlB3hvUo85sRRQSPAA703r9YeNFvYdDvAKqtcvqp7D
KYPu+X60LrWrxLgM2q/HS2YYnFyeD0XPRUOptNojLyHi/Ah1BSwronnMs5wdv1PRtMS5RgbM
GUVuYMnTH1qSB5OLS8UwyrgVTU7RtOt0r/XGhRQel1nio9d/uNVuh8O+1WL0vrbGrcFK0Gum
fy56KafCKcn3WVNqLZfoTgGp3lzf1Yvq/SRKh1Z6YsYy0gd2c5+dJH8ToSqHT/DmXoGc/KRB
ZQ6f4L18r1NS2Bz7AO/le36VoAK6zg/wXr5H8Uc7yPcO8Aq+Z2dXej+Fh1cG3XP+qN2qFFPz
jQgyWH9oRTTtVK/tfTKaaP2VXnqOqVUDhbrLGqHufjqB+zEZTQ3PTX+BdZZm6MRqOIku4Xtn
jOJzp73diyaYm0g1dhLrtx+4Y28J38unNtDv0+H4DYla5tpFVMB3waw0IKxD+TEZTgk127CX
Nn8fKFiUjodefO+v8r3NQofSJXUFm7gGeC/LK+KXKfAsGuC9LE8khQQ0ODPzBG9dZbLwJAE5
1ADvXeUcBmKokOAB3voJpdTU0ALuAC9gEg+D9bOzd5hk0D2TjMykWnOhruh8dF7TqnfuFzsX
S0lSgt3RY9AEniiea/z/M8fjC1mSyZVRlUzShGqIc4Nrs+JWS1QvbhPDIONWNM7WnHx7NOzM
lQ1u1VvD8S6EDmfDEdJczFowcNCwatV49I+32u1oQgXLl6VSdSYONx7O7bUXx/t+nUPRHNU6
8AA7wHtJAPdU0JmHAd5M9TQZ+BUe2M1ET1Oc6yDRe4L3foMavrcgnR/gvQlHa/61oLbEB3gB
nWC9SLIMcwy6Z46RM0vpVYqzJFCZlyav8f+RzruoqU1FUxLFWUVU/NwqoHFJWdN3aKe9bR/T
a9P8gmCNnEVSRRtXl8gUXZdvhzXGrWiCtJUStojMvfm9YivVOxVvfJ8Oh1WZqUYSPDoPv1Q7
5g7XmwxHnd13v1q0h5cgGs6cRtqL632j2qH0mjqczntgN2fzahIDBwQHeDPF49RRobUndi/F
U/MzDZxkeWL3Z/IIXeEDvD2TZ9gJ9YSuIHdXtdphikH3DEucupOfTlHjVDQ/7g+tyOO1Cynr
qWgiJfcwIaauFe3p2JHHm1wbNY+m5lysMFh5joeW5PHOrXFoWGLcisZpWu7mm8w3m3EBuWpe
4o1zncebDEeoRyq6Ze1Wda9hyY/32u1wtAvnh6I9E8Ph6NRr7UXuvl/nUJRTFrCaN8B7OYBk
Z5aoYcQB3svyakwhMzpu+wRvTuW11DqqFXmAN6fyasoNrXsf4M2pPL9AoN0NA7yiM6+dsz0e
5hh8zxzDOpdWVbuyGKqmt4S71ouh29loiLOqZmd7ueGpvBU1aONze7q5aEKFMrNKSEJ2Q+0a
/aElbO986JaHNcataIK3SRRWKFp9FNSLWcP2yqO2cr3VbofDyoXCya0X50eo297cmCo8Ev0x
HY4W7WFC/HAuAa8WkQD8Hdkew2zvxqEBDpAuEZFdNiCyX+AvV7BENsB7GSi1JBllTwd4OwMV
AeUzBnjvPYM4+b0fvGcc4K3fYfOvpSioBT7AWz+h1h4JTuw7HOAVXYMXHfs8vDv4nq+KlmYa
jsJ+WQM77Wjy4PlzMZnPi8lz0UhiKr1m5wS1VpCBxkMr8o31PAc0F01Nzbqp/wZzWC/CsyEr
xKkf1lrXO+3tXjThq2LZiXRhbcwwZVvjq3I6PPs+GU7YsZb/BwAA///sXVuSI7eu3BEDIF7k
Bjriqve/nwtIxf44jqpB0Wx229aE7TgfyTOCWCom8chs0ru/fPz+lh6mWDEacqX6MhsNGfmu
sHS2bEs5Tg42/3b++d9S+KvJhuQB3kv4JCTGklq6A7yZ8MkdhT/5AYU/hFJ7crx/gPeWbtVP
LUoWlwd47y4DSemY/Ihf6BVJxwulPxoWHnTHVsF/JNbU7x0G3cByuQZftCIaPhVMeUxGU0vv
NUKpzCxJB9tYtILy9XOlv7lotKiI9Qo9GgCShQxd0z94pfRHw8DjVjSh9NdDuLD506Y9edCs
UvrTc7fk2XCMIlMfBsNkLZmG8FVLxoGvEtxT4aAfRU74CFo3lbQJ5dxF9s35fl7pL8Z8ktm9
Ad5cX/ZTk5J5nwHeTvaAk2W6F3Yv1VPyAyT5Yhrgrd+gX5hLzZqqDvBmqqe1SJrpvcAriF47
o0Z+/A6LCLpn3xE+emJVoTIlq8u0xkdPLsQ4ZqNx0tqZqh/CgJxVLVxirdLpguhNRaOlyXOo
QgG1Qu4XG4uWVJfPqMTXk/ZxL5qoEzdnwyH94rwoycJX6fxd9BJOhyPWRLiBcYV0890aGn5h
FTMXDhZUDatxJ62c/eXgpELmm+j9Jp2/5NTtgd2c2mvFIJmWGuC9TEBDACrr2HqA9/I9qwVr
Ml0/wJtTe3E2ZMfTD/BmvtejCJpteBzoFYzvYnqEhlEE3TPxcC5K0eal0gCyjG+FUQRyO2MV
j8lo/Is2Z8UIziks2bBQJzvg/5LZOxf6mwvGuRtKE/8XRC1ZaNclhfZLoT8aLhG3ognqRgaE
4uRVsj1Diwgf9oti7mQ4fl9B5mdx2v9XdpR2zuHsDuGbCse5W4+RbQDusU9ZwjeVE38Tvh8W
+tOWHRo5wHtpHna/tSZP1wHeSwCYSraX68Bu3eMoa0tLXtsGeOs3SNhKvGqSYs4v8N5PGHMq
kHSGHuAFPIL6+dgmDYMIuifab/5eF+ehzK32rPyxLRkZ6RdJvaloaqmh28tir/8mOd6KpDW2
0wLh53Q02oyUneepQlbxquiSAWG4SB8Pe4hb0YQdLVfU6KU0hOQhs8jEluyPj9rtcDQeMmwx
MGKN0km973XR+5wOpyGCtm5U/YqU1uaZq62/Sd7vUPqzrB/vAG8u4HJpmh4QfoE3c70W06Bp
pT9ekU24NR5shVr2GzzA29O2mu3eHuC9KUenwK0lT98BXsL1LvqnhjkE3RHsD9G+auZUApx6
ZS0QFyn94UX71FQ0TkI5NJ1b4ygRZvuNVnRP+V97MZwxFQ2VyONBDIUD16TwEE2aZ90p4A5r
iFvRPAu4YuKR9JB1znK9NQXcqzmgyXCErGs4AlprPR3OityIc72LZoHJcPyyF2164o8bi2ap
61yz/pvr/bjSXzKfPsB7CUDFApasig7wZpJXi7W0nvMLvDmlFwq2Sen8Ad6c0rOn2lkypfcC
b0/pMSVLnC/sEpJ3cfQOdwi653Xh97QQ12Xu8BRlydGiFelJ5Yssy1Q0kZtTgh5mcy07dFTX
aMDYKQH/nI5GeyewaEKVnpbaXjKB+2zruH7SPu5F4/ymNugVY+K7Y3JmbVFCr/JZOI/pcFRb
FKB7q6QtOR+9I6E3GU5DwNibXtksaUn0Tuj9sxX/0JKivwO8OaGnRSTJpAZ4M9eLirFkXdpe
4M0pPXFylKxsvbCb99iKX/qze/wCb07oQYFkpfPALmATeNqW4+fvMIege1YX3dgfP/PDyilF
2rl2SXeeXRy/k9GocEduZq22pHNtLPrudN5UNBSmKgIKgmicjIaWpFpf8xLXT9rHvWginVcZ
QGJUlXty3GqRtjO2c8vn2XAEqar0xiz+tKWJ65I54qt03mQ4nVCqmpifl2bZ0m3/Vxp3fIva
HyZvnrhE1WDZoMgP6P3lTqEXdHPjoBXDpJHpC7udeXZNHnsv7NbdpWqFOSmS/MJu/f60U/H7
e1Li4gDv/YTg79ya9FUa4BU5Rj5jN84HhnMF3XOuwEbcpPr1rPvSZB4Ll0i+nI5SPCaj4aI1
5lxUm1JLNnXyEmVmtNMp7c/paAAs3Eq0S6SyktGseBvXp+PQ9ZP2cS+ayDE6fW7URKFa2k93
xaW84ilVe0yGgyUyctFtK+TXg+yVDZfwaDgri39Ob44fQgA9lD1ibidNPKfu+7+deP6nZP4w
q+06wHu5HlHpkh3xO8B72V62X0n2+sYxtkItWSwY4L0sSuUpNJV7+g7w1k/oFMLv1smnb4BX
8LxTjZT/Mx6eFXzTsyLU8DRGi6kmmdGaeiUKnKd95qLhUnuo4Ak7nUjqFMaaFTTvVP74czIY
KUEgkiKcZcUvwNnd+T2Ch0/FrSCi5Erdf6B+k3B6l7z9rhJGudBwngsHo4cz5nVYuSpk52SX
9HDCn5+w29EQ+tnoRBVC2TObkKd3/XgRudut5+dPYrbNfYC3s7qmyWH6Ad7M6rgYJtnTAO/l
d2CFkrfoA7v1G/SDstTk8NmB3fv5gIoI5bIqA7yC27Xzmh4PNwi+59Sh4V3P1MEkO++3xo8M
lc+1Xeai4dIBuh/pIUPNNevU0Vcw1Wer2NnROxmNsAlyRSerlMxp+6IVan6A5+IuPMwgbkUT
pkTmF9nunKgJptVQVlimX1jpPqbDaX4Xqs1vv8CQ7xNsa5yBz/sEZ8MxqxVfI+aYLPDApADA
m+b9JjW/pCjtgd3L9cLKLJ3BO8B7uZ6GX2K2U/AAb91jf9WGSFhSze8Ab8/lYdbdboD37jJU
CX+LrJrfgV7SL3hxDg8zCL5n1OFUhalG3VazUi+0pmor9bxqOxcNFydHoZyoIerHOf7qi5aM
/7bzUtpcNFrIoiyIlbV1TnbRrPGfrRfebDysIG5FAyVcR9Aqhij1c44mV7VdMs18lTieDMf8
iHGC1Pyy5G+gbJ3Tlgy6wNl74HMynKgnmxL4/zVpl2RnW8F/pTnwv17OLywf03J+Ad7clQcl
64X+hG7uyaulS3KiZoC37rC/HdJdeQd26zdINc7prJTfAd77BHYqJMmc7QCvyOidmn35qTs8
IPieLj+rQOOq1J+SHqnXOq8YB9GLacy5YGpxYsehoRsSL0npaV+0IppO50p+s9GAVGDt1XdG
s2pHvmhJZfAidTwMIG5FEwk96BztqVUZkroDsWpFG5te5I4nw1G/F9WG1kGgt3QVeg35vkge
z4bj9A6aRHpSe/J0ndXeefO736Hk17M9Wy/s3iO2ml9vkxWmF3YzzTNnvklX4AHeS/NChrln
B6cP8GaiZ8U0V3c7sHs/n1mp6fmVA7yE5l2cvsP5ge+p8RuSSVNE4JpMFcWiFWm8U4uRx2Q0
TtmQQyPOWkdJdhnFohWF29Mh5s/paIRjGLMjx3RpluctKdxeCbzw8H24FU2MUTzlgFs8bWki
sUTfBfVcSmg2mpB3Ed8Z6YZS04LNK2jeZd12Mhxr/oryh8x/O5aneXMjZW+a98Mifn6tT7aB
HODNaTy/rPZknn+At6fyOOuxPcCbU3mt+PspmQw9wNuTeRWStusDvD2Z1zA5mjTAC5hE5QuW
N7wf+J4vByv0Gg61Grf4bDZvjYzfRbF2KppIzAmTOS+iXPOpr1hRd+50Pl87Gwqov8H83K3k
/yRfeYua/E+r6F+P2ce9aKD4rjCrf08eFCd/28tSeRccbzIc53hRcjbQGOnO/WyWpfLOLkef
8+GgcczWEnRp+L0+yG+O9zs0/DjZIXtg9x6wMVYhyY7kAd5M9HohTas1v8B7iZ4+1cGSRO8A
byZ64F9LUvNogLd+Qgb0Ww4kc94HeEk671zhgofxA9+0sVAwacLmdC850blIr5lPde8ek9HU
gsymElO2mr2y1jVdeU0uciyT0WiH6pSVojM+2S69yIANTh3Lvp60j3vRhB8FgwD3l59zOp+3
ZHgYLu4Uk+E4MTIg7q35DuU9g5cw8dOxks/pcBo5A29GtYenc3Z35sZKfjvXq9+h4pe8rK0Y
2Ls1SJAcIVjwilzAi39MWZCSL6wB3lziDiH4ZGrjhd37kAkWguR5PMBb9xhDdFGzbn9f6L28
mEK8KnnSDPDWT+h/YdiiJQe7DvASXnyhDTK8MviOf0G4Olt7Klxrx+RtqS1pmUOBi3bGqWhC
/NBDCa9lBW5ZJrlCg/R6WmUqGi1+DwLT3v3Wku3u1cIr1K3BLm5gwynjVjRYumDtGCrqWikr
27JCGSFSyH960m5GE/V3Z6egqFQrcrabcUnVHurFsMrk5ojAc5aI4lWVPMAmOyp+Oyv+b0kM
clJwbID3Ej4OodWkDN0Ab6Z8Gtp3ST51gDdTvtpL0+wM9UDv3ecmhTDroHyAt37C1qWAZeUG
D/CKmjdcHMTDNIPvGBlYVAvIwpxUNTuSE4uW1LzPonlMRoOl+fHLTviqIHK2gr9keNxOZz4+
J6ORYsgYDaBh5ZwLRpY0nV4zvuGYcXNrnPFZlYoxZJTOuS9hfNgucu5T0YT4RbX2JH3q5C87
nrxIX+ficjG5OVyBnRgr+amU7EiIRW/Gt4bx7dcdlKxD8QBvpnq1ZFu5n9DNNI+KX6myNO8F
3kvziDXE5pJ57oHenNnTAllj9wHeu88Qee2s8PUXeklu70IfZHhU8B3jgFZMmkmkCwie0jCp
3N6amvfV+TsVTeT2FJDQD62k2tKqzN7pDPnnZCz+09NQOkHTaAPN6tAsqqle8LxhUHErmphu
d5qn4famnJQ99UUrugHR/vic3Ywm2myaE6Lq10zh9MAHrfAnvlShmdybUJe2MCmv2JOpnrcK
zb9Ad5AVc2xlgPeyPeFSNTkoMsCbGV/kwZJ8L6Cb2Z5ICYeFJNs70HvZHoofwEnOPMB767jW
SoMkmxjgJVzvXHVQhlGF3LERaH4Gd3Sex9Sd2+e+87bkDEY9db57TEYT9slokUHlaprtp1jj
uWx6zvbmolE/TmvrWK07sWi5rJ5OnsE32J4Mw4qbe+Nsj2sHbFVQs3XcJWwP+Hwwfi4aJ27s
L0eyGPMPipSleyu6Nc+9UT6nNwfCX7H2/gwnmw2Ht8z036Z7PyA62Hry6BrgvRQPuRAmj/8B
3kvxmOPVnDxeDvDWXRaJV02y9WeA9+4yUMlKzx7YrZ+PKQb1ksXvAV5Rtz1Vt/ODd9hVyB0L
gRijblGvad06JDWA1hQ6n33yZ+fuVDBOCJAhJi45bcftS5Zk885nCuZiqaU3J98ETofa00Im
lZvsK+ZXKp0J2309Zh93dwaltSadxGrWxMgXLclN4sVNYioaKE5Vw7OxNW4hxJyt2q6xEbm4
SkyG0yF0aEDAPKpkw0xo0b0J3t8neD+lOig9udEDvJcBkBVskKQAB3gzz+sFqmZ53gu8l+cx
FU56RRzYvd9gs2JJM9cDu5flgRTOTvMN8AqW1y7SK8OiQu7ZhyhrZ2aKnrbsLF3RJQMZV8fv
VDRYqvQeR2+DEMtNkokVXcZRWz0/faeiqcUqGLBgZ83KcMaiby0Nfj1pH3f3xhlE01YbA7Zk
WjIWLUnk/fFJuxmNX307PE0JFfyGlGZGtGSK/GJOeTacFn0OZNactHJWkqZNHVtvnvejsoNa
ICmhdGA3p/H8tFTOuoe8wJvpHYXDebIUeoD30jsSP6GTOioDvD2N13oyTTbAeylebSVaWHI/
lAO8guLhRYZl2FTIHesAckbQBKBxGFMnK2i0xOfqOpM3FU2k5XqVyn4ncXaUllBcsTdPrbaz
c3cqmsjlOY2g8NFtNetXs8Qx6ZriDZOKm3uDvjPVN4gaKqRzeUso3tVlYiqayOU1QkU1snAG
/jW5vMlwWkx2+3VPjMCSo0sw6ab95ni/Q3awUjJTNsB7aQBDseyo6ABvbsvzO5uk521f4M25
PC6KyTmMAd6czdMiLZvNe2I3Z/N821py1naAvzubN5wq5I59gN81arjY+wFMnAyIJoVl/9KV
d8H0poLB4r/4LlF3UtHkdGosWhBNv3B2mIumhrBdt9ZB1ABzv4a6ZgbjkukNn4qbe4PVoFqN
cmd61n8R04M/Pmk3o4lftCLGgCr3p+jRL8nlTUbT/L6n7ExcNWQu/9Oag/QdmoPJ2t6Kqt4/
V92PSjfLqvu9wHvJZw3Fq+Ro3wu7nXqyJbN4A7x1j1uvUXpNqrgd4K3foUoo3ebegAd26+dr
LcYIkspxA7zgpUKnwr3OCIaDhtxxNZDinBO7OXlnv2Xkcj+xaAX3PJWreExGw4UqUeuMXXpW
sioWrSgk27l57OzeOL0Jn+JGIVWY3JoVI2YXSiJfD9rHvWCwMMWoju8NhJZINgG8hHqeTlA8
pqMBrmLUBYSTehmx5lu35nN+a9DvndZCeVGSnkCzfba/nXj+t2T9kvmnA7uX5wmVmnxPHNjN
PE9C9DjL817grTvsN+NaJDt7d4D3pvBUS5Z0HNi9ewwWA0dJoveFXlJPPneckOGfIXc8DayE
yJoRohi35HNra+rJrOeCfnPRxGBEZEm6VfM/2QZIWKB6jHbqO/M5GY2WDsjQpBI0S9aTdbLG
979ZxlNy9PWkfdyLxq87EK6n4tcVs2QiCyenD/6XHenF7O9UNFCModYeIlPwopKpvNyKWoO/
BS5aFyY3x4Bb735JUt/6bArY3uXkRWRvv6JfzUpXvLCbS8lSumSVug7wdp4HkrwUvbB7WV54
W6hmOcpAb/0OpfeSbU8+sHv3GEFKs6xR4UCv4Hl2kdEbfhByz6tDGnbkBuxncHJsPRat6BuE
cweFuWioNO2Veo8uyOx7whet0HhpeMHzpqIxv0VXNKUnOYJcNdnW1F8Rz1rTvp60j3vRPG2x
q2KohErWK2iJJGulq7bBqWD8rSiNrHY1iqxrkuWtEVts52bFs1tTkcT8jmTNn7VsgrK+U3qr
WN5PCfppVpV2gDcn9VrR7Dk7wHupgEYDcbI4OsC7CR+F+kJyUHmgNyf2/GXSk20EA7yZ8hEW
yHaIHuAVqTA4e9f7MTzcIOSORn8rhECRdzTxkysr6kcrZFK4nRU9H5PRVOdu4uTIORIZJLv3
fdEK+tqvmrqmojG/DgIphZ+0WdKT0pYY5znhu7haDDeIW9FgmFs0UPWfQ4iFZhnfGnO2M/r6
mIwGil9XtDcn4039IpZkfLLEOO+K8U3uTaUq5K9RRalJydxY9GZ8f3tMZL+mn/asisUB3svy
MJSOs5J+T+zes5+pVMas0ssLvHePkQvUpDT3AG/9Dgm1RKtyUrb5Bd77CTsXkWST+wCvSOmd
sgg/d4cRhNwztWgdyKhZJWmYK6jFohUpvX5RUJuMpkI3ZIHeEZMJyjqZm7ij9jIZjQmH1rHT
IsO05cgKy/GLIYSvJ+3jXjTg7Nvvs0AgDCbJCxwsybfWyhcUbzIc9V1prfvPR7El5SnCEf5b
d+dzfneceMcYsG8SP5/l//CIyH9G1y9L9V7YzeVb9qcraX8zwJu5XnPqkUyAv7Bbd1iIng0m
SdGXF3hzztb8/Z4UzhngzdnGVjCb+RrgFUzvYhJYhwmE3lHmpxKKug26H8KSLOnHmgXB6KmC
zWMyGCxG6vc7DwY6pl2llgxpt3o+CTy7NaF8SM7AVf1NliPhsWhFKu9UVuTrQfu4uzeIoMzs
P1YPKNujhyt69Ohi7mcuGj/4SNXvwMBO8S15p4i5sRWbA+d3itlwuj27QUMsCVuyuxUmnW3e
PO9Hdf2ilSht0PEC7z3+KxaArNjLAd5M8WppnFUzOMCb03l+SFPyPB/gzek8KVqThfkB3pzO
kwLJnO2B/eZkng4fCL3nA9G6ADozIqSsoG5d0ut/mcybjaZCl45BWBsnZ402JPNmozEVqj0k
A7FLNhr73nTR15P2cS8aiN5JcJan2nx3koOdq5J5ct6hNxuO89SqTreotgr5ZN6agejzZN70
7hCAhQ1bq35NeifzdpK8nxL2k1az2bwXeHM6T4tIcjZwgDdzvR7FsCzXe4E3J/TMuUdysGqA
N++yFW0tK9/4Am9O6InzCsm2D77AK9jeKT/yM3iYQeg9ow7/EZuAGDH2tLbfkmieUoJnR/BU
NFhU/GfP1UCwJusSuMZ2pJ9ORH9O7w0CKVNTI4SWVdjGFQ1glxm94QVxc29iLgk8JMHWs93B
izJ6p9o3j8looPgDhp2cG0Hz23A6o7cinMuM3mQ4XbF7MMSNa5bqzd2wfzvV+xZpP0zSKlzB
qP654n5hTps8+Ad4c+fgk20kOwef2O3003/G2XLyC7yXfiqVmuQZB3brN6g9pjM5qcR5gPd+
QvBbQ4OkBOYBXkE+LyxEdNhU6E0LEYk8Fvih0yzZTeqLVgw2cz+bPnhMRsNhutysCjRkSk6G
+KIVAjbPbuYzRjAZDah06N33ptek550vWpNqvCCfw6XiVjThN1E5xHiEuj9w3+tSkebSj8lw
ghajeTzdf0CWHm1ewqUvyefs5pihVcKG/h/Icum5Tq3fTj//UwJ/0JJcZYD3sj2iMFLKegK/
wHv5Xgi6tKwn8AHeustNsVjWyHKA9/KpEO7DpH7tAG/9hM6OCiQztgd2Bd+7sHfQYVahdywE
JPLxzfzUqtEPlRQMXqGbiXI61vyYDIZjJhyqB9MrZyWsuNAShb+L8czZrWFtYYpCQsiS9PAu
vIbunTlvfD1oH/eiwUJqRk4nmDlt5kdLgrnQcp4NBpzjscQQMGWZuC9aU1Y+25rP+a1h6c1f
U74xnOR6vmgqRf/mer9C349ypYsDu53itayn1QBvpnhcNKnMcGC37rB1KuH/mJOOOMBbv0GT
VrglSzQDvPcT1mATyQ7RAV7AI54aGWcn7/CE0HueEM4hGJ1vNQDQrF/HCgU5VL6o8k1FwyXm
mp20oqr/tpL1/jW9kP1Uq/BzOhptVbvvDDl1TQ4hxKLv7h4crhC3ook+QIhOaRKVisnW4EXd
g+fhPObDCUWhWiXS9U/rmW9st/tLOH981m6HY5E59phQ1GrSgiRWvXneIp73Uwp/3JKsfoD3
Er4w08026A3wXsKn/quG5LToAG/d5afAMGtWoGagN2f1pBjm+MeB3bvLEJPIlCzjfqFX5PXq
xVE87CH0nj1EMxanFc6WkDCXb9E1Ishy6kDwmIyGnY327t94ZavJTJivWTHNY/2sUvg5vTVi
jSzk/dIWtLqkvfNCQ+7rOfu4FwyWGKtoMZegiMmJhFi0IJp6lUCeigbC8EY6MNVKKJYV+Fvh
eON/47kb4Ozm+G+xG4WDD0BWqn5y/vxN+H5Y4E8wSaEGeHObXnQHJPu/B3hzo144RKXnRF7g
rbtcO4TbSvI7PMBbv0OKRJgmLQIHeO9z2K2gJkWcB3hFc9tpj44fvcMZQu8I9tcCtbdeu5j2
ZCna16xJ6120T00GU6M8SEDEUpOpa1+0gq/2q4ra7NZYq6AmrYbCbnZvVnC8epVAHs4Qt6KB
4tROO3G4JNe8togu6W27EHGeDqcRKTc1BZbkqwDWJF2p/vFZux9O1ep3rnCaI01eKGCyyfXN
8n6Hwl+rScvHAd57yFYrDFll0wO8mew1PwrTZO8F3rvLIKXW7Oj3Ad5M9qS01pMDqgd47yds
UoRzx++BXcAnkC+69IYnhN5zuPBLPJPTI5Nqye6pukYWT09zk4/paCqggKJ1ZE6avdYlOaMY
Dz0/fyejCRZRnR4pUEv2gsWi7y7hDk+IW9H4YcH+hPmuV7Gq+RLuElk8OSNHj+lwNLyen216
ULOCX4u43mUJd3Z3AJuwmEg066Ur0m8r3r/P9far/HXJdoQc4M0ZvVqQkiOCA7w9oydpzYkD
vDej13rpmFQtGeD9Gb20JcYB3p7R0yyLeGFXkLzTi7wfvcMWQu/ZQgBxyEw3acZZRaVVCb2L
ku1kNKFhw1axY+vJrkNftKKcbu0iyTK7N60xgF+kVTHpwuuLFlwnatWLou0whbgVjfObUNd2
mte5sybzk8sSeueGz9PhNI/Gf9e+M8x5I95vT+jNhlOFGnUNFy6sWQ3Gd0JvBcn7MZU/y51g
B3bvCRtDFpZsIRzgzUyvF+rJqbIXdu8OE99Qcz7Ae3keWqGaHP0e4K2f0LlR3Oazitgv8Irm
vIskiw1fCLsj1h/SzE2sQzAKSIrs+qIVCsjSz50UZqPByk5dnVsztmxlvay4C17qOc9GY+J/
evVgpCW5RF0igHMpsmLDFuJWNFBabxq8FYkpO3e7SGQFLiT+ZsNRUWeQ/nZ0oodJJfQNes7T
uyNIVYBCzdmS7six6t/I9Oo/XuTv1kRBcpZgwUtyAS/+KenB2pKZpwHeXOYGPy2y2oMHeO9j
JjGnn+zHG+DNGVDFsNxMXi4Gei83pl64Z73VDvDWT9gpVOuS89QDvKSr8SyZ44xl+GnYHY8D
bE4+DMUaWOfsQEFbQ471tHL/mAynlsoEjYxFsaa7NFeUcpwcn4+uzEWjxVkKdtNWzSx5tPqi
JX2Np1T/61H7uBeN37Ib+U3MvyfLOuPyokEcO0+CzgUTznTUKgAp+NsneZFf5GcHdOZq+TkZ
Dvo71JAobGi4p40g5V3oXsX1fkp/MHT10/qDAd5L+ZhD+ynJVg7wZsqnRZL2ygd2L+HzV22h
rN70F3ov4YNaQs01R/gO8NZPqAIFKFcyOLArUqGnk71+Bg9DDbtlQWFORan66c4hGZJrXn8u
WkH35HyAdDKc0p3kCYuzvkpJx19ftERw+jTd9jkZDRcU6Krop7BAsj61xr64nlaJv560j7vB
UIPWG8bcsCSvSrFoRZHY/vig3YwGClsnZN8d/9nUZFXEVy1hr6eCip+T4aC/oLC2ruwxIWZ/
N3O9L2+69xskCIGTd5QB3szzamHONuYd4M08j4o+RxdTRO8F3sv0ulqxlnw3faH3Mj2Rglkf
rxd2b2Kv9jDpSib2DvCSxN65s4gN9wq7ZZDQC0E3DgtjTU9e+aIlVW88nyKdC6eWp6gGg9Mu
TgqF1DXBdD6Xmp4LRkuMsAA7I9Ym6bwerGF6f3zSPu5FQ6XGgASKxXy85siEL1pSJObzaam5
aMApaG9Owqk1vyQle09DJG1JYu/swvc5GQ6GeWmr/pAZkGWPrzI3fPlmer9IhLBmyx8DvJfw
CZdKlMxKHeDNhK+XRsl6+ABvJnwAeQmdL/RewsdWoCfPhBd26+ezGla+uc93YJfQvYvOs+Fe
YbdMBVrBKIP7tb5rTfY4xqIVxr9yavz7mAynFrSQze0qANSzLZu4Qp+m1YvE3lQ0XCT8mJ1U
+P5o8voTTclL+N4fH7WPe9FQiSF1C1Fj5aToRKxZkti7uFdMBePEzRojawhOx+5k6d53TyzP
hmOtNevRdwy1YjZP+Rad/vt87wc0CA2z/fkHeC/HQy6U7CU4sHsZXtSLe3Lyc4C37jGCkL+g
kpXRL/TeXYYna0tmHQ/w1k/or/cCknwQB3hF+faK5Q3/CrvjKWDRgVGdQnRFzSrt2KKcnlyk
WqaiwcJk2MKS1qRBshhdVphNo11NF0xFU0ukJsk0bF8gm4VfY8aBF4LmNtwrbkbj5KH7I1Y9
pCcjzjVSLrhdVrgQNJ+LBvxJ08qhS8NNOdn3AEsetetBlslw/Efjr9Kmxl0wOco6a/zyZnm/
Q4PQb8NJsneA99IAslLzQ8sv8Ga61517pDUIX+DNdK9iaZqcfPhC7/0WOxfWdD3xBd6bcsRW
NKnVdWCX9OpdHMHDuMJueooIA4GGqktL5lB1clrxL616F2PLU9FgIWDCyrV27slWSlxjFtxO
nSs+J6MJdS1nrTGe0VTScjsrLFIqnkbz9aR93I4mTNdCSsrvFi09Ur4iFd77uQjhXDRO24A9
FNZeqWKe7C0xSTm9JX1Oh6NK4SQJTvpCWPFbh7DfZO/HRQiTJccB3pzSC8fzpJfhAG9meVSM
konvAd7M8pQKJMUUBnjzLrfniZDc5Rd4b0qvShFIJh0HeAXLO5W687N3eFfYHT8BK9SVqKFf
2KQnNZVsyWGFYheJlqlosIhzotYBuhAktdR80RJxmqs8y1Q0tXQFBietRpWSZo+xaElK76JP
bzhX3IymEoXbmlVqz5mCXEpvib0uXtwnpqJxviatdlC/eVXJ3pl91fcqB31Oh+M3PP/5azNS
keT9KFa9Wd7fZ3k/pUJonByDf2H3kgCG0p9zYamRjBd4c4deZOizExlP7Gaix1oUkofgAd5M
9LAwZrWPD/DeZF6IM1oymffCLunPuxi8HbYVdsdKQP2uphLKzNVP32TCSJdQCRQ8k4t4TEaD
4SAUCRYPyulr8ipTVrzB0PCiPW8qmihbUnN+1zweyLbTrql1Yj3bm68n7eNuNKgkyg3Av6vk
haKu6c+7rNxORROVWwOW8IPqgrS1cotXcpeT4WgPh0sBJ69MyYJerPo30jz6DgnCpLTZCk2z
f7LUHyUHtQ7sXlpS9akekBT6e4H3U890ofYAb93jSuB8Mj1SPdBbv0UnQyWajJKyKi/w1k/Y
yYpmPfcGeMGLxbfjnBYMSw27Y3OAUqh2qw1Fq2azz75oRZFP+kXv4FQ4/lKiDsad/Q9QVk1u
xQwZml7Ir01Fo6USWtMqRgJJ/VBdk5pDuehSHY4at6IJ7YPgNooIT+vq1IDIHMVJS6U8JoMJ
MQzR3kKevEoyX4NrZrUvdf4moxHARk6pm/PQtPDLW+dvGdH7KZ2/cABN6/wFeC/jEyq1ZWdF
DvBmxidFRbLSzi/w1l0maFo4WaUa4L1VW4NSs8JmL+zePcYawxJZB8OBXpJwPOd7bRhrtDtm
B9hLq42bcyNUTRpbxqIl882nDOkxGQ4VqGDO+Ay5Zh3haFLH4i8CMOdpoLlorFSu5ISvGYEl
VbdtiUy1X5fPc9tt+Grciob9Xmatd/B9saxDKS8yPTlN0T0mo4FirOEO0tWc76WHK2wJ42t/
fNRuhoMxEdyVwSlspaTBDr4Hgpcxvt1Sf1B6VudngDfXlcX/0qQY4QBvp3qQbiE8wHupHlYs
NUv1DvDe1B6wv0OS9Y0B3rvL0Z7aKEv2BnoJ2TsfFWnDKKLdsr3wKxtVIw6lXcJkzQ/WdPDL
qSnJYzIccm6ASFGTdWaRrf4vIRTYTjfnczIaK37ycu9+BEePZ5LrrfCLca53ca0YRhE3t4ar
VurAtVZI2oD7oiVSNhcT6HPRPGcroiMS/VlLdhIts7c7NzKeCwYLOb8T9ete42wSGScT/G+m
94uk/lSSWfYB3pzba8Uo+TwO8F4qoFDIX2i5X8wB3kv4/H1RGLOeaAO9N7unvWR9Rg7sZsIH
Ie2SVMX8Qi8hfOdTI21YRbRbAv79eS2ihs3Ekq0csWgJf23nRrNz4dRoHjYgQOphS5AdtFgy
gMrnImxz0VgR6ASdlZ1WJPt/fdGC7khnfBd3i+EVcSsaf5OEaVvMOgtrUrrd1ywIhi7mk+aC
Af+WnetxjKFLzwpLwpq9AbmgfFPhOHvziylI7Q1qTxen5/Sgfh3l+38AAAD//+x9S5Ikt5Lk
iRoC+wJ2gVxEHqN7FrPofoue+8uYRThy8SjuZQ4ikUUyKM1iL9RfhYZ7OBQGM9V/mttfz/Ym
D/BemRfLCyYPmgZ4rwBgKmhJZ64B3nqXO7v6hWTVbIC3focEUpolWwkGeK8MBSotaVh2YJc0
7F2cqo2QiH7HuV/iB9LU/9DKknRKj4sWsNFTM5vHJBuMw/znaKOvvJyMA4uLVvTrXQwGz7Lp
vYEI9trxhtffkha30yPCryft4x6bOCJsQtV3jFVaUhPNHhHeqelNsYn6nEB0C4SzZDq/Q1f4
MF5Z/c2y8QeNFAnAF6OsSebb6u8vbvUnyfPRAd58ghvNG9nxjAO8Wen1ojXZ4/7Cbr3HANAL
tqSX0xd6e9mWenb++wDvVXqdi0jyFHyAV2g9Pmsy9xV4BET0O7b9rQiyhTmHqIvm3G+/rbFN
0dN52sckG5cG/ixYB2MxyPZRlBXlYOh0bvU3xyaSykIWQSURSv4eVsWbnZrjfT1pH/fYYLjs
S7ghg7NKnkbjkikgJLro1ZtiU4tQE1V7pia3pN+QX7XGh/GiV2+KDhRfKP2e++bCJWy2Z7fU
dznvz2u9H3D6S97gA7t38cfIAEzOPQ7wZonn+2lNTowM8N5inlAx4tyCMcCbi3lWenKncWA3
l/LChDtp8vfCLpAQyBeL7oiG6Hf8+qOHtUV+rWqD7Colaw5rVS6686bYhCWcyzpllSbZUQxc
MrxwXcqbZGNE0siocTT9bzx6vi7ljWSIW2yiKscYRkMAhsnOyUWlPDrNSX5MsomqHAL5H60B
9mRQ8o5a3iSdHr6LPXwLtdU0nbk+nre++z08/iBbQxngzbU89d1Qdhjjid0s81x2WLZJ/wDv
r+VxyyrRgd5cy9OilqwrDfDmWh6WbGvegV0h9eq5yW4fwRD9jlt/K6wQ44OGVilJqC1xpQU9
PYN+TLJxZRByGKG3xpJMUoiLVvTlnVoGf06yoYJgbFIhDIOTHoy0KNPsqpI3ciFuscFCwC5A
ujGEgs1W8lZ0sj3LoNdP2k02UcmL2+JbpHAoSdoW1jUZyZeVvEk6Zv6bqb5k+r3RbM9RqX9L
o5Vv8fmDpH523IK30bIhkR9w+sNkos8Ab24bbNHFljxmPMB7JajUUrNWnQO8V4JSlSLpULaB
3votuqLMn3gP8N5PCFYgm7U8wCuOk6+kwcit6HfCBHppFTgivTpRtZw0iIsWsGG7EKFTbLj4
GmooQJG1lqw3xkUrjpPbudn0LBvAMBYhFwUMyX4uXjKpjYAXjQsjtuIWGyzVdTpz5W6QnAaO
a1aQOc3geEySgQJASgxMVVt2swMrBPWlAp0iEwoUGluXKDPX5BRSXPV3VKD/LKu/rHXyAO8V
fMQl4gyTvsQv8GbBJ/6rzm4vDvDWuxx5sKVmB0W+0HvllPYiybPOA7v181mtBSk5iTDAKwRS
vViER35Fv5XGwfEEcmTIccWsRSUvWbl8v3Nx6jdFxzeh1Qy7/+5bp2QPCi8pbEE/zT3+nGQj
pVdqqpWIjZL56HHREr13sbMY+RW32FDh5hKpNeQwl8x6O/OSA9kLb+c5NlAiVZdd8jXpLq+y
Rbo1/i+/fNJus/F7Ir6bbFRrVozDpDXPW/D9vNMfxIBq1vjlBd6s9Kj0bFbwC7tZ53HRlvUD
OcB7C3stCp6UrN9+obd+i01rWIwmTzoP8N5PKHHAmvuhHNgVOg/OhJEvviMlot8y74cCVcC1
RKTJWPIFv6ZCAcoXYyJTdLgYdLaq4r+rZ9RWzjZ4SVZwv2jummTTTc2sRdmVk5vHVSbI7ULn
jZyIe49acRJGLQx5WrIpEiYb1dJ9d49JMrWEuR/Xxi71pCbjLusSK/TrNsJpOtHdaa1j42SP
5yybt877jXz+mJOdegO8ucms+g4kOzNygPcKPn0afiYLJAd4b2GvR6ZENq7hC725sGdFLOmW
OsB77zP4bsK39MkBuoFe0VB4cZZrIyrCbvn3N//+esUGHVEh+ey2oisOc+Uiz3WODhfQpj3s
b305Tue2wYICEtjFUjzHppXq4hUR/WVr2UmltqaAhPrLR+3jHhsqtUNrFkYj2iin+uKiFWwu
TnPn2PhG03+N3NT3S1Ux6QbhVy05aT+N3P6cpAMFSVrrYkoEaUk+tza8Vd8PW/2pJetmA7y5
Z68Wyx6dDfBeBcBhKZvt2TvAW++y+BoNnLzLA7z1OyRkfxkmj3he2L2fr0LR7G5+gFdovH4e
qmAjIcLuhSoo9NjR91ZZW3bhXTEqBs+A1rOFd4oNFgxbSmR/L2UXqrhmhcI7LVJ+TpOBSDVD
cxWB2U0PrmkKq6c+218P2sc9NuBizRiFBKtIejx4Tb+e/vJBu8nG9+eda9f6jLNtSaOhuGpJ
x97Z1uhzng4JxVB9q0o1aWHqV70l3gKJ92NWf5Zs1hvgvUoPW+Ga7FoZ4M1Kr0cXR7LUc4C3
3uUOYYefjMUc4O1KL6ujntCtn46rS51kF9gTukLjnSav+9I7QiHsjlW/+G2NaLbeRTVrZSFL
chRA8Hxcc46NKxzDJtS0V9Hk4X9ctOLs9jTy9XOaTUNX4ByjZdWy8XmLKkWnJdavJ+3jHhvf
6BgSNf8HQZLmE3HRijIeXxSMp9iEm4uwa++O/p9kNMwijXd1djvLppO5WoWu0XVI2amMufLJ
W+P9tMUfJCe/B3hzGQ99P5jMCh7g7WU8qcnUswHeXMazkl/OD/Bmcdd83ZWkb+0B3lzIc52T
9XEe4O8u5I1cCLvj1h/qMzz+lBmoZVNSii6YfAE9bfZ/TLLBgiamHLEDKkmDIyy04uTZTsuS
n9NsgCk8ygnNavL3EBd9dyVv5ELcYhNFOf+hGkjcmqSH57JK3vnIzxyb0GtNKol1gspJa566
RrPS1VntLB2GDsKipKppW+p3JW+FyvuZSh4XSBahDuxeqUcRj56sogzwZqlnhXo2suOJ3VvF
MysVk2cMA7xZ6EERySYEP7F763jUS9NkyvIAr5B5F37ONiIh7I5Pv5YKzWL99acQk/Uiv2hJ
lvBph+Fjko1rHPHvqPVaqWryAYqLVtTyriosk2xibIG5m8YZXTpKeInMu5jDsJEIcYsNlC6t
dq4xZy3ZU46ywqf9Mpptjk00VLOvLr6HQ6eUL+atGbi92FFM0vFV0rcUDatW4WyDof0l4zr2
abj//tf//Ov//et//u9//gdU/+c//uv//O9/bl2okmv8XnmUHVpY8FJeoMJ/xOuQI/YwuRi/
sJvP0p8NK8kV6QDvfcgEwg8oucoc4M1F9XD4ThZvBnjrdyiqYa6YLAgf4L13mdgVAieDab7Q
C14s0M+tb2ykd9idSAUq0Ng3M0JWSZLtebRmnETkogw2ySYySHokzSlpcjMcs0sL2PTTGMDP
STbd37DSOsTEuv+ba2fra4aIn9ry+kn7uMem+r2JQnivho05W9JbcW8uR6Jn2XTfVETfZCVE
Tg5tzkaRpG0oPyfphKUkRXqP3/fKSZ/6WR/Kn1biv1e99Se9DllLTxv2HuC9ko+pmEqy7HqA
N0s+LVyTViIv7ObCOrmGS6dhv8B7BV/z22bJofIB3nuPsfu7DpMdnl/oJSfs5wFnNjI87F6G
h7/pDYEbVuOkyRktOfd0kXnR3DbJ5pldG41tvaVHmZbkm732eWer8BSbXnz5NaZmqNSTp569
4AoLHNSLrcWI8LjF5in4qlAlIFex6UPcJYqPTn0oH9N0em+E5vqVMErKWcW3xqv7QvFN0YFi
0URpvrEQxuR2GyYjNd+K78fNDlHCfS/pfnOAN0s9LJI90hjgzVKPIgQ5a3f4Au9tpiQtJkm5
PMBbv0NVLeEmkfS+eYE391EAF7Rk0MoXeoXYq2dVCl+CR1aG3ckwoMIu51mhWpVnD13ObXiF
2NNTf97HJJtnuFJksrgq7pLtgyi0JMfktGXvc5KNudgD41ZfjRDJN/OSCSB0/fKrJ+3jHpta
pPtPVYE7SBPMVZDiqhXqqF6MZ03SaXFvIvcDrGXPS8IxZ0W18qq8N0UHit+RzgT+j3TJKXGY
zAZ8i73fxfGQMJJyc8/uAO/VfOKLp2YHaA7wZs1nLuOy7eEHeK/mYyrakybcA7xX80GPuOGk
5jvAm090RQomO/cGeIniu+h3G2kZdjNfotYu0b/HVJMZXHHRivLe1TI8yaarUevWGvfsAE34
4C8p711MNUyxidzyRsj+PTXXFskuqbLC+9MV30UheaRl3GIT2o1q9IhGQTnblrNI8V22Vk7S
0WhFNMauWhukR05WtFYCXHjhTNGBwkJcXfFxOB5mZ9h5qvb6Vnw/6XZoUFr23TjAe1UeRLhU
sl1qgDfXfPwv5aTDzABvvctxpigtqUMHeO9d7r30mnUvP8DbD5p7dtRzgFeoPLlQeSMrw+6l
S5i0BqjWGDg5U+UXrWDzdAU/W3qn2GAkVHZf33yhUum5lTcuWsCmnY6wf06yoWJNpAJUJky6
V9DkudofRN6ZAP960D7ukXG51iLzo7nI03ReZly14gy3nd2bxzydCHdTNDNRSTsEyoqia+1n
d+dzkg4UUI3KfiQANcoG1s01775F3m/gd2itoGnSEucA71UB5H8ppOekX+DNWs8KJg0SDuxm
paelU7Ipc4D33mPD+EuTVdsDvFfpiRaoueLXgV2gJcBOTUp6PeIx4v+5pfMwmv85PIclr/OW
+FrLaV7dPBuFrgJk4dadTWBYolo7ns5JT7Kh0lBcGimwAOScoGmN5SG2Xz5oH/fIhGLTZgSu
9sAwWS9aVMwjOp3In6fTu28nXHMxMieLI4t0Hp7mk39O0okEyo4SQYKinHzW/KKp18Bb5/2k
56FRgayT2wBvLuZJEcy6fx3g7cU8yBrNDPBmifeMoEwKqAO8v5iX9cIZ4M3FvEhCS7YODPCK
Yt65RUmvMITEvUwJ4y4NXecp1vQu3lYMrT6rbWdL7xSbqMv5mttaOB8CpycJv7mYN8kmCnPU
WzcgoZrskl9WzTsrtH49aR/32LjAUWONiAwFSA6tLSrm4Xkxb56N/2yIBdFqy9YcVok8Op32
nqQTxTz2e25VkSXZqxsXvUXenxd5P1HMk+rPImWPow7wXhXAtTRLqtEB3tyeFx6myea3Ad5e
ziNMNvsM8OZyngtM5ORdPsCby3lSOiefwwFeUdBrpzORveLQE/eiJSwsuRCQmATTJbAV6kjP
7Vbm2aDrI2ok1f/ns3UJWzKQcdo6+TnJJjpj/cFRMqmcDu9dk/rRTjNMBpmPe2RCtWFliLAM
F0fJX/cyrffLJ+0+nQ7VhR4i1E412523Zrzk3Phwkk4U9Cp3dZnXBbLxDJOhiL+71qO01rvT
c541NVnwKlo2JbLb7s+fKE4mbwzwXmWCWjj77hrg7fqTIT0S/ALvrSjXOHRK1hoHeOt3qNgL
ZgMIB3jvXa4o8b3k7vIBXtI4eDqm2SsNjXMvw0ND4hiSYrjuJqtzK5pIQE6D2h6TbLhAcy7M
rWOtkqs1+kUr2DQ7bdmfZKOlg0X6TQNrLfte9t3YColzPno+2HzcY+NbbXTt6buCFgPOyZnT
iPBdQud09nyajjkNV9Lo+x3KtmDVNZVguCo2TtGBImad/SHu1nuyDzIC4P+OAvQf5ffXsoNn
A7xX8QkV4qSeGuDNik+epyhJxfcC71V8vZeadXQa4L31PK6lQvI7HOC9d5n6MzkiOxF8oFfU
HM8tnnvloSvupCxQAVKzRq2rQs+OBC+poMqplcVjmg37IsxMzKYtm9bjF62oOZ5bPE+yCbdm
fJa2oLmWzf0iVlk8y0XRkYequJfn0YT99yoVCNtzHPy38HieptOJjbRpZA33ZMNqXLVEwp4a
Dk3SwXgPCFLFpqLZqsrke+Ct+X7e8e+ZspW7zQO8+Xg5/tLsTOsB3i72Kia9uQZ4bxMBydPI
M+n49wJvLu+hq/TkdzjAu4u4tWC2RvqFXiH27KLAJ0NQ3EvAYHGlp7W5qM8OJaxIyYkEkfP1
d4oL+w+eWa1rx4qcYxMXLWBjfFHem2JjJWY0wVfgqqhJgzxbUnq9HhiRISbu5V/4dqdXitTs
1izZtbpqYIQvzpcn6WiUw7ULQZyWZ5XrCiPx6/LeFB0oirVaRXNZbMktX1z0lnqLpN5P+f0p
t7zfX4A3l/d6UcgmuB3gvVpAfXHXbLTXAd6r+FjCOiVZO3ti9+q92gsmcyUO7H6115NHnwO8
4jD33OvP/4KhKO6FX3AV10bqosKX4LTX3wp9JHgxsznJppmE8xM1UkmeF5LfnCVq72JwZIqN
FVJX4uzb1tak5rRrXLRE7Z1mtw02H/fYPEctEEU6CHdLd9+t6I2kUyX+mGbjIhya1d5Usvcm
LvpurTfFJk5lDboxoDZK3hu/6G/ZS/i3d/rrljwkGOC9+g6sGGCytHyA967+TP6STfbdv7Bb
7zFyKz07AD7AW79Bqn7bLHmPB3jrJ+SI2dNk5XuAF6iIpzPD2brbhoq459vfMBYpJWyUTOaG
JR4jLnwv7F+myGAB9d+8KXW1bEEYJwcc/2D/cuq9NsmGCnQnwtWlMFFyw0hLeg8RTuecvx60
j3tsXKvVuC1QXUK0rMVIXPWtzYePaTpK4VYowrUya1rirTi5rVfjIpN0DJvfFm1Qu2VNJevk
oNVb4/0eRn9KySCvAd58eMulU3LydoA3S71etGcPbw/wXrHXrXBPJkkO8N673LlkzRyf0L19
hP6VNE52Og7wilLelQdMH2rinl2/xUEnsUuJ8Kbd6gHDZ+vVY56N752aS4qKmrSKimsWkLm0
gJkiE5niShoT2w2eMRo5C5jvHaT9etA+7rF5DtI2VxO1KdbkWdGq0I7TKefHPJsWMi/OoQF8
Hdw55Xzh5zxJB3x7ILVHXKN/WS25ck1GAr5l3o/6/GHp2TmHAd678qM/WJWTviUHeLO+868l
Ozv/wm4v5Ul2+RvgHyjlJWfZBnh7Kc9fhMnfyQFeUso7TVLo1YaMuOfV3wilIyiiYFrhLanl
6Wkv+WOSTZTlzJcq61rFkkdoOJk8cKeWN8WGfAnVxmiVhDC5H6OCS4pfdjHvY0NF3Ay5qEgI
ET8SRbDs2MKaWt7piMxjmo761tdcSbErPYasxvv+Wt4kHcPoZyXn1NLprO9a3l/b5683Sk47
HuDNtTwt2rNTtwd4d9NWGPjmfVYCvL2W52ti1ufvBd5cy+uFBbIRci/w3nqeQUn6wLygC9TE
VWgHjGAIuBvaIa2GJ57/N23nvOTQ9pTM40+Qqf5/rbKRZRsn1iSQtNPq1+ckG/KvWawzgd8Y
SGa8+kULHrTLGQwYsRC32EQdq5HzgF4rbS7m0XkC75+gI91cEvlXBbR3pOSqmDdHJ4p5tUJv
rsPFkvM+MNkg8LvrvG/x+IOkRxKssK3767r83fBw1p/wcEZopWny7TXAmyuNViyZS3pgt95j
wupiLVu3OMBbv0F1was12c8wwHs/IfWClmwaHOAllcYLWTAyK+BeAgeQakUzir7Bb7V5+Hcy
p6Z4j0kyXMRaRwNQDMeX5AzwnFHZHyz+zoO8ZtmgSGM4/k2WtcuKvPY4UPzVg/Zxj02UDGv1
28OtiQClx0JWFBprv9jqTNHxDWVT33RoU2HIvu7Lio6SC8PCz+mbY6ZQYy6stQ6WNWefC+L5
3fXnP8jir/k7JtkSNcB75R5x3lNlgDcXG59GLlk7kBd4r+CzXnoy++zA7hVTLoJb8qTmwG79
fC7QS3KC5QVdUWiU86Z9GIEVcCdFACPjoWEFIfVlK7dg4ZLmJ5ALh905Nlx8karI1uKf5Kkl
TzY//aFr8GL5nWKjhUQIDRmsQfLwRxfN/8p58wKMvIpbbGpRiGzC+KKg553wVvRiXJo5z9EJ
lUNhuqgm6HrvW6XRv+vW08H5z2k2gggW74FONZtsX+Z6jd5C73fw9SNNFvQGeLPCo9Jb8iBv
gDcrPC6anWEd4L0Kr7vwrcnRiwHe+h02122191wNY4C3fkJ/rApA8sB7gBeoCTr1ePD1d0RD
wL3YDu4Y85nRPyi51TeuWdE7KOfTIXNkOJqZOSypoXZNBp3GRSt6By/6uebYiIscbj0O/Ju0
ZJlF1iijerWlGLkQt9hEQBELgesi9Ucu6c1al3gKub48062PaTrdHzFiY8EOmjzw96vW0Pnl
s3abjlGM/7bm/wFMGgLUyf6Ft9T7jXz9WrId4sDu1XtSC6UzO57YvWpPa2ktecA8wFvvMPdW
ajIN9sBurudRiKNsE8ELvPceo983oOQsyxd6SV3vfEYTRigE3Iu4CONW0O5/Svbkxi9a0kF4
4eI8xya2JrX64hu+uskfIS+ptUA/NRb5nCTTSqcW59G+IcRst29bol3xslN1JELcYlOflaOQ
etDEdUX6AHeFeKXT8+jHNB3txgbs31RFzBv7rbAprHRR15uiA4UEKogouexLj9HTVO/RW+z9
qLEfRrZFfho4wJt79KL8ney3HODNPXpYzJKRQwO89S5jbUWSq/mB3foNuiwvqsmncID3fkKQ
AsnX+oFdIfBO50193R1REHDPnp8FWmfXJ+FTlj1/4hVuL3qa+vWYZIMFRaWJonA06SWrkyua
2kJTnq+6s2wqqcTsE3TS3K4b18wCVzxj8/WkfdxjUwu7boRGLomga9JSJK5aQed04uUxTccf
316FIea0ITkP6FetOFZ/BgRdP2v36XBl/9mYsghCms67nrdA4v2Yrx9Sso35AO9VetgKYfJF
McCblV4vtWf3Qwd4r9ILX2bWbLDdC7xZ60FpWSvxAd76CTksI5OP4YFdoCewXmi9EQQBN+35
G2mLFOheMVuEXhIsBXLqYvOYZBMWLlTZt07dV+BszX+N70uzi2reFBvybSpHdEKvkN5XrGkD
w9Omtq8H7eMeGRdt1qtGYxv1iJjbOo2hF10Ck3TUX4qq2IQb1+Qc/aKUjsuj20k6/pjVCrU2
s9rSFs797e3356Xefm+/xknnvAHeXM1Dl21ZJ5ADvL2aJ5yduH1it9fyarI28IT+RCXvTiFv
ex3Pt7vpOp5jl2i7iyV3ZEDAvXgOFqROLC2iBrIjdovqeGe9X49JNlGSIw1lwr5MJcODl9Xx
zuN2p9kAsd8bBVJKDsTFRUv68i5GbUcCxC02UZGrIKoc1sCcfNQW1fGIL05qJ+mo+L3xTWVt
LJp8ky4Sd5d1vFk6XCms2wW4Ze3b33W8v7KnXwx+57a/B3avwoupiuyQyABvVnj2zBxKm6oE
eK/Gk16Msg7YB3i7jrKedEce4L1VvBahG8nGhhd2gZq4CmKDEQIB95z54wjNpQT22rKmKovc
m/k00uIxyQYLALmYIBcSRMko5LhoRU/ehXvzHJswYu7dpCK3tG8HrVF6V0kwMDIgbrGpRUBb
uKnU2jqnTfDWTNpeCL1JNq69XeQ19V+3WnpiYYl5M50W8z+n6VhY92A4qvuOr2WFnk3tkX53
oYffYeqXPNNf4e57a4QgOTyw4A25QBT/lNFgx2RL9ABvPtp2IW7ZQ6sDvPcxEyiQ9SN4Ybfe
4xgnr5wUnAO89RsU7QWT59oHdvO2h6QoZM+BB3pFG+NVUWrEZsCdKAMtgGIdItM3YlaTHiew
ZE7ldOrmMcmGShOD7iqS6dkkmVKRS7oO+lVFaoqMFTZ1Tex7B+ZsG4WtigA5q+V+PWgf99hA
YRbfd4kY+RYs63Cyos6OJBfuM1NsfOWLTkxsvgNTomSRZvYo+N9vDp71ZH5O0sGCHFsvFN9N
GmTNCeb8NH53SfwP8hnU0mvWLvcA71V7TMXS4boHeLPaU39NJ8VeQPdqPcKillzVB3iv1mv5
qekDu/f+klrB7I/kC73iqJvPy1I4kjPwTpqBlNB43VzPSxfObVFksvDxh5nk85GVOTZUtDdC
8D+0YjoHZMWgqIu98zbGOTa9NDbuHTgifZMlQ79ohTy6Ens4cjNusQmx5zuKBjEcZS09HLVi
xPpK7M2xCdnmX5I/aNKrQbKlaZHYq3bexjhHJw4B/KdTiXr3XVLaXP7tNbhI7O32GpSi2QVs
gDerPCxCSZ+qAd6s8qiIZAeTD/DWuww1egBrcl7lC731W1Rt/sUkB9AHeLeap0KSNpU80CvU
3mnqhq/BI6cC74QHaFGxJoxq2FvSok+XjFmCnI55PCbZcCGONjOu0Huy14wnfTT+Xezp2dn9
5yQZqMUlJDWVZOHoecEKpXc6E/H1lH3cpBKZ8c3EvyXqmGy0iYuWHHWfN1XMsamlIWAV33wR
4bMFJaX0VhT3/S8+75+dvTnaLXybMMIfk8NRMLlFeiu938hqMNuUd2D3yj3hgpbuyXuBN8sA
K2E5mlQBL/Buued/a09urA/wXrGHYaiRvMsDvPug3kVwsnA0wEs6Gy8W4RFUgfeCKpgRjbp0
6pD0ltYl5RaQ0watxyQbepZbKvaOPWZZkoW9FdWWy1PcOTZWWMH5dJVmaMm2C7/ou+XeyKm4
xeYp96yTgZpy8kx6kdx72hJdP2k32YSpTJPGMXRNwj070LuiY8dvzvkp7uzN8V+Lge8lm9ae
zG6ASRvzt9z7UbNBKJL9+Q3wXpEHrtso2WU2wJu7uKKmkDxbHuC9dxnDQxeSQ+gHeO9d7lbS
/mov7F4RWm+M/wzwimoenffp4YiowHvpIUaNJKpfnXs6J24uNeDfJV6/OLudZFOryyJBRHU9
nD2CWmIofZUIPMfGX17QpbqOYNcQyXN1v2iJP9+vn7SPe2yq72af/QHkr5Tek2ancdWKw9t2
UdKbpCPRqte4sTWrycZDv2pJpx5clI6n6IAvlL0DsJhpT9db3516KzTeT7kNNkoePQ7wXhFA
rWC2P3mAN0s931Anzx0P7GahZ74TtaScP8B777GRC5BsHOAB3ttI2HuR7Pn3AH+31Bv5FHgn
MwBLj2Pbbmox4Zv8zktfIVzlVBw9JtlAMW2V/IFtStncO79oidtgOxsw+ZxkEw92pxggNb/z
2TnHJTL8WuqNdIpbbEK0kWu9mPBCVdks9c5KrY9pOmLhK+1kmv+6KTuovETqPZ1Erp+1m3Sg
QARGPmdmekv7FcyVAN5S74fdBrtl1/8DvLmcJyW5sX1BN+u7eC+nBd4LvL2UB8kPeGC3F/JY
si4iB3hzKS8OxZKu6wP83fpupFPgvXQKY5dE3T+gsWWHm4qtcRy8aMybZPP0Xfb1j3zlbVnH
wSWpLpelvCk2cQ7BpAh+h5ppjk1c9N36bmRT3GITSq2ybybI4mQw6euwo5Q3SSd0EFf2n07j
5FTJjkreFJuo5Cl3RWNpkFz835W8v7LfYC2YdQ0f4L0qIBxdJOspfYA392z5X0rp/vwXeK/S
I3/jZKs2A7y5locFe9ZX8gDvreU18/dcsroywN+t9UY6Bd7L2ujCQoL+GPqjmFVHfY3Wuyiw
TLGBOIRu3RA7VUs3GC05hG52UcubYkOlcyXXrs3FqyTZ0Joc4EutN8IpbrF5aj0l31QAWW9p
/+IlWg+vtN4kHemM1MEaStPk3YmrVtC5as2bogMFJJwgofo7BpNvtvAG+zuKPfoOz8Hkirti
rf1ru/slEwoHeK80QS3Skj+PAd4uQJmTIn6At97lBuFolvRrHuC9pTzshSEZ/jfAe+9y7VYs
axh6gBe8WPjKiWNEaOCdWAOOZCJUfwg7dEnaUsZFKw6TTwcaH9NsoKmpVKIGlhzQ4iWzs2B8
5ivyOcmm+b7FXw8RXSdWk8XGNlkBujMaMgI0brGBMCT3S57/Wjbac4khOcJpLNBjkk0tEcTH
lVVa2Elmk/hW2OFeTwJP3pwWcUC+NVDfwWWNLPyiv6P+/EcZ/LXszNkA7xV8Qv4+S/pNvrCb
5Z48872Tcu8F3nqPDSxcuJPusAd4bzWPY1uefAoHeHP/QNMSmVzJBoIDvUBUUL0QfCNJA+/E
G0ixaqbasZqQ5Sj5RSvOYwUvugen2FDhRmHyR9pYkz3GtKT/5HoWeIqNFe5G/h4zUs0aXtkS
01CsdJ6ngyNI4xYbKIyIzVyKE6XNsdbE2Z3XTx+TbOKoSGKTxNaatGQ5qa4pB8NFoM4cnTi1
8d+MRdFRW/LNFhe9Bd8awbfb5E+jDyf5RjnAm8+WI0kim+F5gLdrPajJzPUB3nqXfZvrEjgb
C/+F3lzci/bU5GowwHvvswKWbLftAC/QE8Bnh2S+Ao+ECLwX3iGEXaiRdtBkMFdctELr0YXW
m2LD/lIS8yUYVdSSxxR+0YqTfzuNx/2cZAO1kJkwWFT3klrPL+IVVim1nx1gfj1qHzfplGoh
90jBFR9lreTqCulKfJ4TM8cmLFz8KTNoCv5H2tF5kfHLRSF58uZEaGKLfBUXsZLty5gr8r/F
3m/k8wc9WWgf4M3VvV7yue0HeLMWqCWZPvGCbtZ7WAtkz8O/0Hv1Xo0UgmRlZoA363rTWIuz
wv5AL1F859U9GjERdMe73z+asrA26WaWXIbjoiXVvfN+wjk2VKJAIUDGxC1pUU+lr7CB6Xq+
Cs+xsWJizBGjB9CSq7AtiVe5FHw0UiJusXkKPuoxhV79YctqikWC77y6N8fGpZtQjckeVH0Z
R+cE34p8Fcbz1tXZm9MAhaJxgECSc9tx0Vvw/enZkf1Of+mo0QHeK/LiTNGSL+8B3ny8R4Va
NhrjAG+9yxQzyUkfvQO79Rt0We7aPDkyMsBbP6G/CqObKvk7OcBLOvbOi3o0wiHojmk/hvqs
0efmGqUncztwSd0I2C4k3iSbaAM0FEaz9GhZWWK0bacJep+TbPzVwCYYBshiLVmHpyUxJHHS
+qsn7eMeG5c3vs8RdQUR7qtJe4I62RX2h4HaM8X6mKcTE5PdZR76NjjpkelXrRjePu9A/Jym
Y027KnCrvpuo2XHnuQ7Et8j7Paz+ODsgPMCbD3G59NaT8xkHeLPW677NSWY6vLB77zFKOJMk
O9cP8N573Kn4aydZtD3Am4+Y/cGqSeOUAV6gJ67Gg2mEQ9Adx36MoU0jIIA48kyPB68o5z29
+M4W4Ck2UKz2Zr70ck3PmsCa1sNmF+vvFBsuWIE6+BdFoMnR7bjoW9vbvp60j3tswqtBkGs0
t/VGyY3SsvHg80GgWTrSqgLEniIG67P1PFlygHvhBTNHBwqKWLgEiAFmMwnKXGvPW+r9qNUf
ldrSVn8v8N71H6FUThb8B3izxsOS3n0P8OZ6nhaCpN/WAG+u6LXSIZnPMsDbK3raskr5AK84
tD3VRb72jnwIupd2EZ1TER2PopocJcQljfLXFb1JNjHn0YhUDblnk0i+v6I3xYYKKcS8DDG5
3sseQa84UI9H4ldP2sc9NlGbQ9Iaowy+oUh2tiyq6D3n+K4ftdt0fPeGzTeZwhrBc9mK3pI4
3quK3iQday5WjUT9PUDpEZM5L/S3zPs9LP/8vZ+3/AvwvU/4/wEAAP//7H1LkiQ7juSJhgIQ
P/ICuQg/RUutetFdi5n7ywDuxlhUiVnC+BiMyFcu77NSZjqc5kYlPqp/le05+dCkWNSB3dy8
BQWzpdsXdi+fp+i5S7Y4DvDmfF4roMl2pAHem8+jkMlJfsIB/up83rCHoJvWHc7vSJAMnXpl
a7dL8nnSLwpqU9FEaq4REqg2v0FlFWpXDG9f5/OmouHidyyqhK1Hh17ape3L83nDHOJWNJHP
a12AmZqiP8pbpZ0vVMRnwxET5+EVjJSyzZOL5P4u83lT4UQ+rzUPSP2alL1V/F3zeV8i95c1
U1hipPBnC/4lE2UDvLl50Ipl9V9e2M2pxl6yFg0Hdu8Fg1vRlqzmDPBechfieFST88AHeO8n
NC5JqvaCrqCedkEIhnMF3bEToKLSauPWyCok4/FFS2QL+0V9byoaLgoATm0MnAlK7n4aixZE
0+q5+u9sNH63ByQiNpGkR0os+mrqOYwrbkUT1FPD8VgYYjwkW3tdQj3PB10+JsPBAqZ+Z6vc
fXOSj5ovWsE84bTW8JiPRvwFygxVELKNUL7o78g8/6OE/lq2q2yA9xI94rxAzQBvzjRKjLxl
lZ1f4L273K0QJHONA7yXSkUGNtvlP8B7dxme0kItuc0DvYTyXYxoDgMLumMqwMWJV6ghc2Mj
Seagl9AKlAvF3dlosGPXKj0KsckJzVi0JNt4Lrg7F42G7rZEA78TC00WYnWJ7vb1MPCwr7gV
TXAk61artJCsTA8DL8nO/f5Jux8NiH9JtbfWBNIcaYlS9YW1yGw0iobQa2gmtfTezNXI34zv
Ryj9ZS9dA7yZ6tHTwT5J9V7gzVSP/UeT/akc4L1UT6gIJlnKAG/9Do17oaxk8gBv/YSdtFBL
KtMM8AqiJxcjwcMogu7ZXtSqRg2ato6Wy+2tcaVF5YuEy2Q0YX2sz+NXe1LciNd44vVTKbnH
ZDT+ghUNs9swX+OsqU1Z4Z5dEc81nWn4RNyKJloBRTs0INLO6bLynLLIv6Uqz1SQP6bDia5b
rkqtC98wQP5aU5LHZDjBQRHZ6R6iZjX/Z4nrm+r9IJ0/tfQ59gLvZXwChZI39gO7l++pv6Eo
mfJ5YbfucNNaODvQMsB7E3vsFFOSRdIXdu8OE4WwUFII6wCvqHziRXVteETQPf8OCsup6Ouq
1jjHr33RCseLK03nuWi4AJBRj1ous2Wb7mCNwt9FqmUqmlaIxDmrCGqvSRkEX7TGMZh/96T9
uhcNlF79RWL+X0PpkPvxwJL+TifMv33UbofjvBVAGvcWkntp+ZevdVd5TIaDhUn9UtGiXzWf
pOS3pvNfnxXZLfFXS3aA4And3KEX6fLkzWmAN/fokf+lScGSAd66w/6Odc6b7IEb4K3fIdVa
LFsVHeDNnzDEepKKay/sAg6Bp0MVfuoOXwi6p9XfsSFI79Xv8EnT10VDFSoXfXpT0dRSRZtZ
7ULZCZ462ef+rzVbvEjlzQbTmwIFfwjrrGQ0tGR4Vs4mmz8ftF/3ogG/hBkTY9wmLNsc5KuW
tOmdNjt8TIfjT29r2jwW9YjSCs5LJrX5jHw/5sPR9mwJDYEhTc8CzzmQvPndz1D3a5bUVRng
vVSvWqGsq/oAb6Z6rWBWh3iAt+4yMRQ/35M85QDvJVIhwZ19Dgd46yf0w7fU7IDXAC8p3J6n
WHhYQvAdnf5gFMpNGE1NeSejQIHzI3g2GpTOBH64i/asCmhZQsTbhUPqXDTk0TBwbFDMZGSV
X1bo2Djz/+2T9uteNM4MQgYvGlYtJPGy+n4rbsKVTgdoP+bD4cqNDLA5d00XbvVrU62P6XA6
+QoJ4ZcmmBwo9FXvbN5fZ3vfIPDX0yLOL/DmjJ6/k7NNvAO8mebVItl67Qu7OZ8nxV+xyW/w
AH9DPi85FzzAmz9hz/9OBngFybsQXeNhCsF3hPoxRpa1M/t1KKzjsxm9Jd15p72GH5PRRHaO
q5oZV7DkUMmqlB5fkLzJaAha4yrCYfyVFeShFf1ftZ135/GwhLgVTaT0mm8NOAVv3dIV2yUp
vStTttlwVFiqk7zQcrak/9EiU7arlN50OGoMzX86RuksxTul92fL+1lPim+8sHuZXgxXpKXf
DvBmpteLZGduX9i96TzFoj3ZeznAm9N5VF6Zq1Q67wXe+gkFuPSabA8d4CW9eeclNR6WEHzP
rsP/TAWhbtJb1q1jiY6z6hlt/ZgOBjo1rOD/pAVj6hKD10sd57lonqaNhGGeoKG9mNVxXjOh
ej7ww8MP4lY0flTUWgUxMseYPWJi1Qqid+HzPBuOVqkKFJN+ijVrZfblzmxz4USPk1/o2d8w
fptMOsP8Xccw6h+v7ndrkCA5Q7DgHbmAFX+X5mAHTE6uHuDNZe6Y8EhaKg/w3sdMQgsUcp9w
gPdmQNlqCX/4pHD4gd7LO02LZS8XA7x3n4nZz+xkL9MnekUWtJ/PrfAw0uA75gaohbh16sHB
sv1MsWjFWK9cUZapcPwu7F9SNyOB2rJp6iWDo9hOrXEfk9G00vw1y6jVwzHIbU4sWpIGPUvq
fj5qv27vjTQhM1X1Pz3Hv2iR/uBpbfhjMhrwr7n7r4aY1CrlfX6XqEP2iyzoVDhxQ2xoYlVN
JZmijhrj35Ec/wcJEFqhrKvkAO9lfX54AmeNTp7YzZxPo46d1aR5gTdzPumlYzJRdID3Mr5O
oRCenJk9wFs/YXfGAz35CQd4Bd87nYX1Q3jYafAtiwMphjGljNg02Z/1XPPVdG8qGoraTO9S
AdEs2agZi1ZUvU9nJR6T0YgTpFqdUJA/PclgZInAjrO93z5ov+5uTQMAv1G0BmpJgZ1Y9NVs
byoa520YuV2S0LnMvgkWDV1fTSnPhYOFUbCZATkXx5zMJU6WRN5s7/vFB8WfxGRT0ABvpnm1
CKbzUi/wZqLn54YmmwcHeC/R00oFNJmD/0Rv/Ra1WUHLCiQe4M3JPWpFJS1J8wQvKXuf+xfz
sK/gW54CVkA6OjsKV6tkQLZE4g71NJqPyWi4sHbogiaMlHUW4RX6Ou1ULegxGUwLvb5uCOS/
wJ5UkWhr5PpquxhiGeYVt6KpJUSZoVXo1SRJ9WLRiqr3VSftVDTg18vqL/AK7FSvUXZieYkG
OOK5ovlcOKEtEwPl1YLpQZrqvZ1FVlG97xIf9FtxMmFxgPcyPuFCyaTUE7qZ7XV/P2m2lPsC
72V7kQirkrR3/UTvZXu+caCYTC8f4L37DDFEk2x7GOAVib0rtjecK/iWn4CWaI5XEn/fCyXH
WWLRkszeRZvjVDj+LISrrLM9X1fT2tlL2hztdALkMRmNFupNqAE4o4CWNNopvESipp1Ris9H
7de9aPxHEPrMfgNvCGzJ4kxZMQdWz+fAPiajCe1spA6mTSBSfFm+tyRTeZp3fUyGg/4bUKvs
BNZaTaqC4LuQu4DvbRcgxGKUPF0HeC/HQw7/iOSF8ADvPf85jLWSmdEB3szk2c+BZGf8AO/d
5V6LUjKJMcB7C8zaS89WOwd4AZFAvpgwGLYVfM+2glWxKVKllylVjkisSIOpnjt6zUVTC1QB
P6o0jOmySvQFVoxgm53rEM5FQ6UzV+2k3FU1W4xe0SjgTPliaGqYVtyKBksHCLqFYPI0vM2N
x69gRXRF8qaigSJdEMi5vf9uWtJgF5Y4UzulvCB5k5uD0hF8Ua2RRc6SvKnr/5vk/QwVwqwO
woHdywHISvgeJEeWX+DNTK8XsqRt1QBvrtJrkazC3wBv/Q4JXiOBuZPtAG/9hFyhACdFxQd4
BdOTi275YVrBd4wEtETfD2q0ZL9yOCmmV1doEKpcaIZMReOkDauYtV4xXSBc4dyKdspaH9Ox
xPi1VrXQp8n2rKwxJ7vkecOw4lY0WJqGcbN1vzxCkoPjmqkMOk20fkxGE4yN0RlXt2bO+HK0
dRHPA7roE5gMpzH7xYhbDfHJpEhVrHoTvb9M9PYLEFJaZvqJ3ZzLCz285FjmAG/P5QFlM94H
eC/DY983zppAH+DNDI+KZsdZBnhvLq9hqZxVbzrAX53LG74VfMdLwAk8xxFlys64kg16vmjN
5O2FyvRUNDEL2BARSEgsmw0uuITjtbO9eUxGEy+HsIsz50aN0+2GK3poapWL3oDhWnErmjCv
wa4A6JeJ5FB0rFkSzLk58Fww8LR1BxNlY3k6OeYo3pJRjNOp6Mf03vjjG12gaj2S+tlU3tTZ
+mZ4P0R90JIztwO8l+pxDLdnO8sO8Ob2vBjIynbnPbGbiV4tnKyZHNi9NA+tZOeBDuzeNJ6z
8/B/zx27B/iL03gy7CrkjoWAOv8UaNH9pa0nL/C+aAnJ4/P0ylw0QfKi4iS1hp9XmuStSEra
RXZlNpqwRRFtDRphUpCkfn3BVoZZxa1osLRWAaiDxPRCOpG3Rkrx3KFwLppQEYybBJCz7+iZ
3Kk9SHKeM54NpzUNEu6PG0S/QzaRN3Uu/HSaR18hPpjUrlphNfNHi/z1pITeAO+lnlUL1+TM
1QBvp56M2dfrAd66yyHJ739rMs34id76LSrFwFz2STzAe/cZlf31y8l08kAveLlUO880yrDT
kFtWJ1isktMD9K9Rs7qFuESXGOVUyPdjMhyn+52YVcTvnZRsL45FC6LpfJace0xGY2Hiox6K
Pz7IyQSQrRk3vZoNkeGmcSuaWkycDfq+hPBLMtcYi5aw0N8+aTej8ROwMUCvztsq16S0a6xa
kmu8YKFT4Tjb92sUij9papg2MW9v2ZdVdO97RP7Ur0XJzMMLu5fzCfm7OWt3coA3cz4piklz
zgHeuseVei9Uk/0Dn+i9lVvmIJpJmb8DvJvbx0Bs1sJwoBfQCsJzezsZzhpyy+1AwvUEBEk6
UFL+MRatmQc+l3+ZC8fvKH4UE6DzPT8Yc6l1KrIi89j5XJRjLppe1FrXzjVcjJOXyb7G9RdP
Z7U/H7Vfd/fGYg6YwmWnSs8KOy9RsznvufuYjCa657A72+tBy0GyoyIr+mDi2f7do3YznBov
esLW/U2lNe0XNKe38eZ8P0HqL5oJ0lJ/Ad5cXdYCaaZygLfTPbBkXmGA99I9rf4TzeqWfKL3
pviqhbJCUurvAO/dZ6utJInRE7qAS/DV6TtMIuSmg0dH8JNKBU2zAl+6pL0LhS6I3lQ40URn
LboI/e3ESQUmX7SiYN7lfCZ4cnOwIDsHR9+hSLlkM6+4RtT5XOlPhkvErXBCtI9AWwwjNEsm
khcp/aGcq4fPRRMevg2jx7o1vyMlC4iwhoafNwA8JsOJoZzI6okgsyRtmX3R28d4FdP7LqW/
BkltiwHenN9rxWqyW2+A9xIBBb8lJecSB3gz4QMnwsni0ADvpXtOKRQkKW12gDfvsobCYNrj
7ECvqOheqP3JsIqQWwL+0SLIqpW6v/STXhG4qq8Qznv658Kh0jgqoKC9dUsmKWiJ9QW2U1eS
x+zm+AvCg0DnFAyaFOmJRWsE8i5KusMs4lY4tXgwxlyJGvYkh61LTFZqvWosnIrG6ZsiYNeo
LiRJUqz56oLuVDBYrPk9qXWuXI2zIj1zSoxvyvfdYn+SPLsGeC/Nw3AOS9YyBngvAYiJ2pY1
vTrAe0v1Pa7+yfbHAd76HRJY2HgmR0cO8N4yM2BsXO47HOAlmb2zt7sfvMMlQu5ZXrRQ5qh+
VkHWwIMnu3X+leKdGox+TAZTC7IBaLUaHbHp0ZElFA8umvamoolytEbHHjszgqT565py9IUd
2OeD9uteNFgYhK37dUIlq8MYHmILoqELU8C5aGLUV8FpkbNv8dvEzskRoItWgcm9cbIqzRl4
JMST0fiid8/eAor3XVJ/jZLNZgO8uYLLpUPSCm2ANzO9MEtKZkVe2L1JW2xFLSvqfID37nHj
wpItMB/gzfXlFhqNyamvA7yATODpcKAfv8MdQu65Q4SZrJMidCoKaSGYJUYkeio28jEZTQiH
VAMh6v7U9rRw8BIhmH5B9Kai4RISJl1JW9Ws76svWkEm6qmszeeT9uvu3rQwhsBK0IyynoCL
LIbtIpU3FQ0UMQxe5MSoczacWLWiHI3nmkOzmxONOsCg4sd6WnF7LonyZnrfrPWHkJwmGuC9
x3/1K4Qm0zwDvJni1dIteVV9YTen8rRY9ix/Yfcm8pD8kphMNQ7w5kSelmxp88AuqdVe1M+G
L4TcEevn0qI3vlKFzq3nAuLJvpx/K9Ve5PGmoqnOOzsxqWpUa7P95EuGb9tpHf0xGQ0VYQ6T
C3HmbcnsSiz66jzesIW4FU2k5AgUtSlwTU7XL8rjXUrATEUTKTluYE6DlfxylPbs+PJE3uTm
QDU1EYQeXYfZRN57EGMBvfsuob8ulpx3PMCbE3la1LJD+gd4L8sT8PMmmch7YTd3X4pvW7Iv
b4D37nG3gllF5wHenMizopgUxBzgJYm8C7G/4QwhNz07CDu2FooeWW6kS5JFqHrRlDcVDfqd
qbGoR1QbJufzcYn2hf+Mzy2z5qLh0NltjXsH4OxbmZckWa/F/oYxxM29adqotl7JglR8aa//
v1ZsTzWQPyajCXc2QnYKSc6OLDl/H6u+OpE3uTlVaqt+2XNWbEkdXZzszf3pTO9LtP6wJpu4
6oqX0bIBkf1qf355yqv9BXhzy6AV03TL4Au8nX8CJqcaBnjrLvsj3vxFmByU/ETvZXg9JLGS
v9kB3voJDWuBrH/hAK/INp4WxZwZDOcKueMn4NvburH13oUxeZS2JUcpcr/IAU1Fw0VBwWrX
xph96/uiJcVku2jXn4zGWLWLmt8OslocvEgcjy446HCuuBVNGPRhKBZK80tCdr5viatfhXbu
XzMXDT5/0kTiWwPUsqRthZN5fWYDr5+029H41pBYPGadkzUHnHTj+ekU9D9I6c/8KU5mowZ4
L+MjLpAVBRngzYxP/GeQloB7gfcyPsMocmQlqAd6L+OTWiT7LQ7w3n1G7PGSTKa1BnoFS6rn
eUcdRhZ6y/ohakutcuUOJFnhotna0r+VmM9Vd+fC4VJDLcU6ScNac0VZX7SC9PUL64e5aMw/
GJuFQA9USus7r4imwikh/3zUft2LphZlUlbsUPUpuJwifStmES/1neei8Z8ANIYG+FTIy0qm
LKGweFr+f0xH4xclJ3vk/2DyZ+Nr3gXmRZxvt9KfFuQklRrgzWSPSksWbw/sZqrHRTWd3HuB
91I97uI/0OyJPtB7U2eCpXPyWxzgrZ+wdz+Ako7BB3ZFao8uaN5witA78v2hGgzmHK9WBoNc
0S8WrSgv83nCZS4aLo43ATPQdIoiFq1I7V0occxFo6G2TYghGNw12byvS9S2nUmc7c3nk/br
XjQYHrvgNxUWxJZMi+Mii93T383HZDRQml/f/F/xvUkPLsaqFeGcDlg9pjcHDJsYa20xl5Ql
rW+dv1U877t0/qQlmcAA76V7AoUomfMZ4L2ET/1HDdmhkQO8dZf9xo5FILnNn+i9uT22Ij3d
V/AC791nprjXZptEBnpJbu/iKB5WEXrLx4NKqKZQN+FG2U4vWpKjuJR3nguHowseFVVQlCxb
Al2SqWx43lQ4F00rHYg6ILVqWUYei1awvt8/ar/uRVNLqMgBYBTcKakmF4sWRFP53MdjLhrw
exwzMjz9nZO66LFoBek79b95TEbj73mSGlrV/qNpySwyTg4qvUnfdyv9UdLweoA3t+1FCjw5
+ffC7j7+C/TkNW+At+5xjKs2yX2DB3brN0iVSk2r/B3gvZ+Q/BjtyaajAV6R1evn/h06LCL0
jmx/TJNWJPO7BktLXufXjKA6Cztv2JuLxumAdL+WOJ1mAEpziBVZvX5VUZuMhtQZXmQozc/f
tHnWijGL88TR55P26140UfAHjwNA/KWS7R9Zwr1D1+R3T9rNaJyqiVOhbhY5V0veRxdJOZOd
0dXHfDitO7MzIGbo7Wv56pvh/QyhP+YbQn8B3kv0qhXqWdeJA7yZ6jVnb9kRqwO8tyfTwnme
k51wB3gvlQp9wZacAh/grZ+QW3tqY+V+KQd4Bdk7nUL1I3hYQ+gdwX4uIuHZ0SGk8ZKZ6Fi0
IjfZz5V256IJeWZsHZ3pKdbsjPkiTWc692qbi8ZvMV07GqC/yjg5j06F1mg6n09n6LCGuBUN
FhKneuqXC/aQshPCKzSeKuFvn7Sb0TjPYVAW7KHDKOkS7hf3HT6mw+kNhchE1IQ1K20zN1v/
JnvfqvVXS9e01t8LvDmdF+OM2fmtA7yZ5dUilG3VP8CbE3rdD+mkmt4Ab07pPb2ekxm9J3bv
52Mu4Sma+4AH+KsTesMbQu95Q4gJVHV6F91TyYiKLJFzPhWz+JiMphYnds7uyAgp24kai1Yk
9E61GB/T0TBqD2Vlk5p1fKxr2vQuE3rDG+JWNJGbI33NR0N+ZHVFPs9/gb970G4GE5k5EGl+
O4IKlmwNWJTPwwuHmOlwemsYlnnAqslqOhSbuk68Kd7P0PtrWaY3wHuZXgxZZLNlA7yZ6Tk1
qkkWMMBbd9mqOgFOqqEN8OZ8nhWGZB/mAG/9hH7z9bdjUgJ1gFdwvQttZx32EHrPHqL5kQWo
5lzFkj0Ri4YYpF+MQ05FU0ukvpBqF5LkDEOsWdKbd3EATwXjjNqZHiApmRJnPYUXmUP89kH7
dS8aLMxdRRtCGPFm03m8RDrmQtp5LppQJCBDI6nq3CjP9ZZIO19NZExuDqjEjd5fMNzTNrx/
5kTGPiL3P//833/+v3/+73//4//81//9x9YDKqmatZcaZccWFryNF3Dw71A8rE0Kt6wx3QHe
XFH3G17aVu0A733MJBxxOcnAD/Dme1YtDZMV9QHenFHv+QbUAd77gjN2Up0UjRzgFQz8qs45
HDz0noMHVWSmEFYPi9Rs1XaJS7JdjKpORRM0z6o0c1ZUJekrvIbmYbuSvpmKRoqZdaeszelR
42R1pKzoLrmQV/l80n7d3RuLLgesHotaun1yxQTh9VD0VDR+tGjI1FfpFNqauXB81Yr7EV9V
1KfCIafgYflMDZyEZ5MfvuhPpOA/K9v6jYKHtYf/YbaMc4D3UgGm0jTbQnmANxM+9dM9mbYe
4M2Er5XsqMeB3Uzqo3qbS8kc2L1kL7Tdk8zowK6genxxAA8LD73jq0ClsjXnEp1BNJvQm7NV
+Ne6ul7I30wF46Stqh9YPVrAWro/j1cMQpucsfDHZDRSyLdFkH3bgZOlaFkzKHPJ9IaBx829
MWfhrCiVIG+TvESn+5LpTUXzZHqRb40hGa1JzcZFTA+v2nSnwvH7fFNtrZF/V/kp9faek1nE
9PbOTzBJaZAdhz7AmyleLcLZqvoB3kzxqGjWCWaA91I8lcI9eQkd4L27LFxq8mA7sFs/X69x
Bufe7Qd2Bck7nYP0s3d4ZOgd5wJ/+Bp0BGRhqD3ryKtL1HtO530+JqPBoiJ+TvVq7P/PsrwV
7wc0veienIpGwwScwlSiYuekt3lZcVusYBfNk8Mi4+bW1G7S0bcmnLmziipLxn3owr5kLhrw
W6WTISRRjd9ONp23ouu4IlyQvKlwoquESMwodsiyMuNzF/83yfshGofMWDr15FTkAd7OApiT
wigDvJnrheJvdiL6AO/leua3sZr8Dgd47y5rXDKz86wHeG9Kr1NplNzlAV7B9y6mZWzYY9gd
04JIhxoTQhc/RpIy0LTIr87OovmYjMapG2vUoDimMihbv9U1E9FnIxmPyWjEv+awYamta9Ok
QoAUXTIRfUH4bNhj3Nyb2hVjKoMat6zD0yrC99sn7WY04X7MTUJxNEhfdoJ4jWXyaRfHYzKa
6reEKoQxYoZZTes6ebV4871vlDesCgVFs2frC7y5e4v8FdaTz+AB3svxOIzps0MyT+zmsrxT
IkhOQw/w5mZavzzUrIzqAd76Ccm/FrNkp+gAr+BEp605fu4Oawy741dQn7JzSqytA2Tr5Gsk
n1XPx1TnosHITAChNsyOqa2ZkDE975ma3RirjIDoPIJqckImFi2gEPV04PbzMft1f2OEO6hq
yOhl2/NWaNM6vfvtY3YzGij6dPlxMqQEyeYXWOTAUi/o3eTeiF/tpEoY/ViyddsXve2IF9C7
b2nMUyn+ss+yvBd4L8sjLQbJDvgB3szyWsnq1h/YzSyvFc5mGgd4M8vjQtlupAHey/Ial9AD
zLG8A7yATFC7OH6HFYbdM48AENPegh71JDWqi2xK7HwSei4a5wXAXJWthwdxtgMMF+SK/LJ2
1gH2mN4baVGkE+beszMydU1t8JLoDSuMu3tTq2C1DgIk6b1ZQlvlvHA7F41zNmzQiDB+2pjk
rYuY3vmc+mN6c5gFBNVfBi3twTA5wPRmet8obBh1L39gk2myA7w5kSf+q88eRQd4M8Wj0ik7
SnaA9+5y60Uh6aQ2wJtJXi2Ylf8f4M2pPCq1JXd5gFeQvKti7fDDsHt+GIA1Cpto6GdVtvd6
Ccm7TOVNRROcQE25tSZZy941CaPrZN7k1hhVBqcSEqa92Y4pW5H+wtPK8+eD9uv21jxluIWM
sfV0onVFrbbKRa12KprgeKqtt8r+ArJkW8CqbB6dSYI+pjeHu7CxdDSzlssbRwrwzfH+Osf7
nmxeLybZ5vcDvJfqccgpJi9PA7y5Lw/8Z5Mt2h7gzfm8MJpLdl8O8Gaqp8VPhGT54ABvz+dJ
z3pHHOAVfXl6QfWGG4bd84/oVqMlD9Qkm4X2NV+dzpsMBkHFJMYWgCl7YuEK3mp2UU2biqYW
ET9/gfyLkp4kR75oiVDyFdUbXhi39waiabKHy3Vy0G8H1ZuKJqiekR9/5ASWIDmQtYzqXdwq
JjeHq4SSPdeqNd0zOTel/tOpHqWp3o0TI9kJt6IH7k+W9VNK3mhf2M15Rme8mh0KOcDbyaff
PbMDwC/w1j0Onb6s4fCB3bvH1Y8cyWq8PLFbP18HLai5xMKBXfBCwVMJamcDw6DD7pmnEEsF
E6ut9aRknC9aMUAhdpFhnIrGT8Lw+QtbOVRKZtFj0ZIU40VtbyoaLU4wGLmF+V7yt6Br7Eau
NF5s+HPc3BqTLgYduVfMDup8uZjfXDAh1sJVmz9r2CDPOpdIvNTTxPxjMhwq6HdP6LUpS3Yi
DP9INe2flV78Zik/w2yO8QDvpQCCpbdkbmeAN9M8J7+c9NUY4M00rxXOeqsO8GYy34plcyov
7NbP13ovDS2p5neAV2QYL5SbbRh02D2Djqr6fM9DQ02/5+uSFOOFT95cNM7aQIw6oL7GAXJM
b0WG8Uq4eS6Y0GCOZhgy1tqyskxfL9xsw57j5tY4OerVSXi4dLRsLntFL5BfBS8yjFPRhCcA
ABohhgBeMi8Ca9QJq14ks6fCoQKNhRphM7Ok4nkserO9NWxvv5wft6wd8gHeXErWwlmxgwHe
TPO4aJIBHNi9JE+lkCRHawZ4M5WnqK8nmfwTuzebZz3UyXLn7gCvIHkXcn42LCDsni6/n7nY
uaIxQ/JXRWsE8PjCnmMuGixRp6TuwYgfv1nNuCXFG2sXLG8qGi3OHjgylP5VaZLlxaIVObAr
eZfhAHFzb2pvlbT67vSetudYIu9Sr4SEpqKB58gOIlcRqJWy9sFr9Pzq2ZTLYzKcWir7CmVo
FTjZTlIntdvfLO/H6PmFRE+ywj3Am4lAZHCSL4sB3kz2esla2h3YvWTPQhEimfAY4M17HAJ9
2RGWA7yX7jUoIElZhAFeQfeuBkSGD4Tds+h4ytAyMZllE0e05NRCuZrNnIoG4xCuYr2R+Wmc
pRRLorGrqtpUNFqQKvgp3FVMa64JUtcIpFzSvWEDcXNvahdtIUVNZElTi2V079wQeS4aJ25W
obemCEqSzI/AIrfqenbre0yG48wtJsTUr0gNe9JAxRe95fz++oTIfjm/Jtl62QHeXNCjkOxK
lm0P8F6Kx1yoZ5trD/Dm4rx/LZqV8znAe79DtWIi2dGQF3jrJ2Qg/0uTuzzAK7JgV4J+wwbC
7onzA0F9quiGplf27b5E0O+ZVj47eqeiQX9Y0TqpAPtZlR4DXmPRcZHTm9wbp3fYe4jxGOfd
sZbQoiupl2EDcXdvKrUqVAUU0l16S6Re4GoKaSoaiH4baK1LByJMvk5hSfq4Qj3bnMf05gjH
+G9F7FKTj5oveuf0FpC87xkD1pKeD31hN1duxW+rycLoAG9mer1gdmJvgDczvVbU0o7KL/B2
pidZ6d0XdjPPi4p7sglzgFfwvHo+mdmG/UO7KcoP2JzhCZNq1g7FFy2I5krtZS6aJ5dAYed5
zv2TRiOLtJv7hUHW7N4Y1to7YtSh89rNC/oNL3leG/YPt/cGqLbWDGWvoh/iedZ4LpgY5m2i
HQwakCWNqn3VkkTrhXbz7N6IX49qNB1as6QVmy965/L+Os3br+jXsmWoAd6cy2O/eCe13gZ4
M8Oj0noyfz/Ae3e5db+4JYtZA7yZ4Wkkv9IqL47dzvAQ0pm8F3gBi7jS82vDAaLdtObAaC4K
/zqDfCZviWjzae7rYzKamLpu/nuSHqQ1qwj59Zm82b1p0BitgbFaUhfFF61geFcqL204QNzd
G0CpGklJM0uz7xV5SYTzcu1cNEHWmHoFNY7bRFrQbw3FO8/kzW6OkJEKhtdW0jo4sn9vhvfX
Gd63JPIM4jKcvNAf4M2pPI3x2fwQRoA39+VB8QM5r+cX4M2pPC3SslMOB3gz0esFOen2OMCb
qZ4VSp69B3ZFX96Fml8bDhDtnix/Nz/Vq9QelurZ8dQlcn6XqbzJaLCyYfPjFxGSqjerbNjk
4vSdiqYWC/8HM9XK2R6LNZm8S543/B9ubg1062H9QAbpIbU1PI9Oc18fk9FEKk/DWJlBwX87
6Yrtl6fyJjdHwJp0ADDKWjf8XW3YvkTND7MaTys6zP9kPT9L+3Ic4L30s0JhwuQnPMDbK8ma
dQsa4K27HCp9KklyN8DbO0ObSlbr5QXe+gk7xkxUUrdxgBe8WK50/dqwp2h3PANCoq8rAvRO
nPQM9DUrUnN6KoT3MRlMqOJ2RqLGUjGptjarintjLmQuGnXK5j89rBJK38mfgy5KzV2IvbRh
TnFzb5yhV78bCLaOSaWpRcJ+2M9VheaigWLcuLMwh0p2clBxkdgLw/kY8Fw4VPzN0qtp9+3J
NQzGkr8j/fyPEvZjzdYvDvBeHqB+0rTk7MAAb042cumWvbAd4M1sr/nXkuT0A7yZ02uRrE/c
AG9me2Hwl6t7H9gVycYLYb82/CnaHdOAMLDz97uIxAigZt/zS67EqhdH8FQ08UKq4O8k8mNY
ek72OBatIHt2cQJPRSOldQsNZ6euof2SVPbrX072hj3Fzb0x5mqkVrlB8r6+SNnvSsV5LprQ
YzZqrbJor8C5Rw3WyC7WU0fwx2Q4ztwovEMaqUjNepyXuUTKm+79BGU/bUnVtwHeywAkFIWS
rdIv7Jd9vv8PAAD//+xdQZLkNg78EYMEQJD4QB96/v+fBarEOeyG6BSXzR7b7XU49pCcqSyp
pCQIZN6pvKIM1vQu8FmVpzWJgBpqgA83DviNhVbhB/isyuuUugsK0OzlDd6h8ybefn3kQfRn
Nv2qzXVE1i7R8I56+20xcK6Tt+8Sm5KqcbHazF9Z+MllXapOPPD2W2OjiVv07XMVKwbebb5o
h5SYmb30EQjx8NpQ6AhWEnI66MHlFrMXljs2n4tscqrKjf2nE2fLYIp23pTfN7H2W2MT78n4
0filUYWdQNKajdqPzPuTrP0ErEgN8OGqXk3+/APrPRf4sN6zZB1NvLzAZ/Veo1QFdB8c4MNX
ObvIhN2H5PD5bY/pFPCZOMA7tN5sUmQkQvRnNv219V5Mqr+GscLEJls/0cn7d4lLSUrNmXBl
fzIJeny7o6lrfny7xOaV5ef3juTOaqARni7GZT1ReiMO4uG1IatExLllzuCeYpfSu62Efy6y
CT9mK3Gqnruilot5y55irvSW2LhoY6KmfnW0FgLDMH3Rj9L7v+dEvsHVD7TCurDHO7eagMbS
A3y4P0+SZNSF/gIfPpcPq0Mww2CAz36H6pIXnke7wEc/oeSaagX3GAO8QxNNPP36yILozwz6
M1m36vKuGjp8vc3Tb3Jmu8SmuLxRX8KmLrjA6+OL9hg3T2p5i9cmJoHDNi7c1hp6bbZMAk+9
XkYUxNNrQ1xrYfPNImqCt8nshWXSCrrEJieXQpJNw9HPd0hog57uaNCbTgIvXpxapWZpkXLD
YIvej6ff39vTT9DI2AE+fGpbU0fPHAf4sNaLyVS0O+8CH9Z6PamitdALfPY7bOTvbPCcaoAP
az3zrwUNs7nAG/QE291Jp7+BRxBEf+bOnzP5Y56oh0oCnYD2+PpNXV+W2ITri0jurTbODDZN
xaKv1nqL18a3qp2kM/dSO9afR5vCXWdab+RAPL02/of6vWbSW0bd2b/ev3mNTTgxa+nZtxQR
WQvOnZ/QeosXp7Lv9JQzkRp6DPVj+7JD65029mN/eqMP+gt8uKAnybfruLFfgA+LPE4GP8Iu
8Nmr3C1JQw0kLvDxgl4DzbIu7PFyXuvgBOQAb5F4k+PaEQPRH0Z0lLBbs15zYTiAaYuxn+pd
o+HnIpso55myhUeZWIdlxJeX8xavTS/WrPvNk7lX9Bhtx6Z2bvgyUiCeXpucNSbGrVTGbbV3
HNhOJd4Sm5B4NUZKGlXjBhqQnZB4ixenCvVqvpUgRh1LfyTe39zZD+yauLCHi3maRFFPugt8
uCkvJ8ngY+yNPVzK01QJ/CkP8OFSHsdsD1rKe4PP6rySk+sJUOdd4B1teRNfPxsxEPbMnN9a
kab+BtZi4DjnJl+/WSlvlU2JSKnGLTcWuCLx5aW8NTaUfI/KQiS+0TJwrCsW7ZAS/a756/ed
9vH02mRrrr65lEZwCsQeX79y3x+wRiZkHvVeODd1oQeaVG1LYrv39Vu9NjVyTCRmfWLsHpV5
/8iIDvoKXz+wMnW6JoW2Rm14Pm6QxN/mNcigDdQAn5XEFBP8YIXmjT0siMPuDHUavMBHr3FY
mPijGQ1dGejzV5nB8+0BPvoJLfsrHkzxvLA7JHG572S0kZthT8IMehQLWy2WWxc0Ga3vKRbW
fifwPxfZ+M+pNnW1UtWFPuw0uMd85q6O+2uRTE1WM2tptUUwGnavxaIdh9v9fvzdRmrGIzaS
mF0P9+p7lo62ZcaiHRpyYj6zxibMZ8ivjt9oUSvEnqWxaMe1mQxFrbFh3xS6Hi4tixTQk4QX
N5J/uiD+VzkNagbPU97YsxpAXp5t4AHtBT6s9TS1Aqb/DvBprWepoz/p3+jDWk9TVXSy5gIf
/YRdswseMMp7gHeovX7Xf+8v4RGeYU8iDVqyUkhN/UbMGdTXsWiH2muTl/ASG1du4f3GXSTa
stAkLtlSAL3Vrr8W2dQk70TfEBUMzhT5oh3Tr9TvXS1thGc8YiOJalFr7BfGCBSvseir5d4S
m1BuajFUJOGWDZ7IbfIa5DzRe0t0KJlYWFpqI2XYhGZtZ/Ej+P4Er8GOzo4N8GGtF2Yo4Ozq
AB/Wepx84wpKvRf2rNLjGCxXtPA40IfbGVrK4ODPhT1b02suLgVs/B3gDVpCaKLzRkiFPUkO
6H5xtdfWLLs+KmhVr+846JZb1fq5yMb3nk3Ut3hNCxN80L3FOXHmNbjGRhOHoQ5lLZLRkDTd
Eu4ysS3+fad9PGPzMjrwy9Kb8+lgQyNvmk9u9w40a2xeDjRNGrk4sm6GVZAPWNCs0aFEEvM3
zQrB1hCx6EfnbdJ532U2yIzduhf2sAyQxPAg5QU+LPZimgJsZx7g03LPNaah3q4DffY6q0s4
QZsJLvBZwSeaOjg1emE3SAq2yUt4xFTYk+yAniqLVa6qLBn8xmPRDrl3e+75ucgmlFsM81rt
VRTu0twj92anuEtsajJqhVpuRNwJeyz7oh3nnqSTst5IqXjEhlPuVJmaslGFkwl3GLES30rx
z0U2OWnmFpMk2QozSCdW7ZB7eVJBXqJDyXcUGs0ctRGaVkM/ESIb5N5xx8GSfDOHvlrf4LMv
/0jcamA5aoDPirywEWxg9+8be/QaV4kWC/AbHODDDbVxkACe0A/w0U8o2XUv2K9+Ybd06U3G
CUY+hT3LDmnVKmnVoh1VrLwlprXobbvR5yKbsCxpnUscRYuBzri+aI+j9KSet8SGUrMXD4ng
dbDVIhZtKRlNthIjn+Ihm+x0pGqtzdUEOm69ReDRJDtkjY1LNeJWexfuORcwpiZW7TiGngwo
r9GJWePwG8w5N/9dov2tPwPKOwTed/kNagYLUQN8Vudx8x8/+Jh4Yw+rPEv+XEGdpd/gwzrP
L5s/oUCd9wYf1nk1wlTQ8ak3+OgnZKPII8Nk0Ru7Q+dNMuJspFPYs9wQVbLCqubPeUZ13o6B
8FLrROctsXHJVqLM0f1NWDOY5xCLNrB5JUPfvXyX2FBSzv76tZKbEGwStCMHhfxH9Vd32sdT
Nrlm13hE5rcxaF0ci7YU8v7yTnvIJhQbuWANbwQuaHruLp3HdwPXvxbplOR7CZfg3KOHEo04
9UU/Ou//1nmnvQYp9QpWKAb4cCGvJrDl5g09LO84+QMZnG+4wIflHSUuYNfbAJ8v4+E1vOMF
vMbgcMgAf3UJb8RS2JOsgKjGdYlcR3+stw5q1S0Tg/MS3hKbqMYVq9VypgZa+56o4C2RicSQ
KKywZCpWUGW3JTFkWsEboRQP2WTXQFIlR9g0nk2zpb9QJh15S2xcoxVrFH2s5A9GQuN/v76C
t0QnXKR98+mMcrMMNn/+VPD+xhaDaql3MBN2gM8KPIlRAPQs+QIfbsfLSdBU9gE+XsPrqAwd
4MMir6dS0AGWC3y2htctkYJHNAO8Q+r1u+27v4FHKoU9iQrgpMy1NM7GXRtcxduSDlcn7m9L
bKIg11zt+caTa8YTQ3Zcm86TdrwlNpRqV61Se2nSwHMB2tTgf5uY+/tO+3jKJpOWEK/+TwXd
e/bkEM6reEtsXlU8I+tsuWW083OT1ivlrsT6a5FOjKcT117Nd0h4OPNa6PqfrvX4K3wGwXip
LcFS22ZCzjv6KaGjPxf4cIEx5idAc8YBPq4/GY3efGOPXuMS7jdChrq8XOizV5liF4vuMi7w
0U9o0hLs+j/AO/RnnpztjcgMe5Jj0BM1alq6GrUO+qLEoh36s01UwRKbONeKjie1YgyX+hcP
w/6n1jg52ltio37bUAy2kMY+Gqs1xqId1bmZqd9IzHjERhJX3+qw9GyE9inFoi3HrhOXlyU2
4fJStZqoqIUd5kmXF5m5vCzR4cTF2VBrmQ3ujklrrsx/uv78V9n6EaMFxwt8VgrU2IGCpyxv
7GG55ypYCqr33uDTgq/hbjQX+Lior6jVyxt7VuxxuLdgj8QLu6XUeHvYZ/lKzYj/80TqZd9x
uMiLcLTOWI3BF+0oztX7oIlFNq7aSo5wYnNt1MBnWCzaIvVu6z+LbNSvTWO/6E2Y0fZZ3XJt
KNut1BtsPp6xkUSdRWrxf7qBqRmxaEdtrt5aCi2ycdEWcb4uw3NuGfdv3iFc5XbD92uRDSf/
imIKqWT/5YBFbV/0o/Q2Kb3zfn6uOcDd1gU+fKasyfeE6JnyG3xY5EnSjkbCXOCzIo/Vrxzq
dnaBDwv56E8Di/ADfPYq56L+CiLwSxzoDXJC6PZU2XIZcuJZUod/sppNtZRIhUA9/faYvNzW
WhbZlAiVUW4uKsi0oYdjW45y2m3c269FNr5BaC7ETXOlZmAsTCzaUtWbbCrKkBMP4yBYInOk
q1QDd0m8pbuTqN1mwiyyCU8/iniL6nJcMjjqEqt20Mm36XWLdMKvjaKRmHI0mIBb7MUclR+t
9wd5+sHz6wN8WAzEuwbN7bzAhyWf+V9acVe/AB+WfI1S6QU84xro46LPKlgdHeDTos+fdxl0
R7jAO6p77fYg1zINWfHEp7/7S0hMKBLawpAW9fXbEs5WJ5JviU3xD9Y7qcsv6Yrnru4IzpvY
OC+yUX+lRlnPGRXO4FyC7skzm/j6DTYfz9i4esviu4oq1riA14b3BBbTbHOxxMbFW5MaW4tS
iRgTsHmPHH9Jsvmd9pANJXKJ2CVCYcQy2uRJS7+bH8X3zbZ+WVELqQt8+FyPH3j6XuCzb/+w
6gNPjl7Qo1e4+l+J/oQv7NlvTzWZgfO2A3z0E0qxxA3UQgO8Q93dTwT7RRoK4ll0QmSIUhGl
YqgB0KaJ4Ho7RPu5yKak+EO5SowFF9C6xhdtyd69HxNZZEPxy5PwoGZx7Y3ao9gWY+D7keDB
5uMpm9wbxTFqJYOtXnaMvHC5HQhe5JKTsmkVLeryW+GIjh2VY38GTCrHS3QiV1WllBYTLx0e
CNalDeuPuPszLP16YVTjvcGHD2+r//jBWNsBPqzxLJUOVkMH+LDOs9QKeHg7wMeVXkcPbwf4
sNLrKUY1QaX3Bm+p4016p2SoiWepCdqlZelVMteGHqhtMaPW21rR5yKbGAju1ekYW0fdv/fM
A0+8XxbJhPeLcrZC+VVe+UO8Xwabj6dssmbqzOFQWEGToU3eL0x/eaM9ZBOTvb4Jpl7M9VHH
4zl21Fgn3i+LdEqqGjEjuRQpuB3mWlXyR+p9q6sfpww+5i/s4SqeJAJnzy7sYX3HLjfAoeUB
Pl7HywUcFh3g85U8dFryjT1ex1MGh1MH+KvreHVIiIfhHN0f6Tmbv3sbXMbbckg7K+MtkYmK
XM7C3f9sMjhi4OvLeEtsKFmJTDwjdVUEbiV80RZDkZm6q0NAPMzm0GZRX82+nUBtCvOOU81y
O7PwuUgmZJoIU/QDiKF9zpvE3bSOt0Qn+hRqiVPaSpHRg9bxlgrGP+LuzzD2a+ipzQAfruO1
5JtasCPvAh/uyMuJDXxlDvBZnRdugmi1doAP67zuj3h0VvICn1V6REkMnFYe4K+u4+mQEw/j
Oao18uuca2MwAmJbPMdk2naJzcvYz99WYXXB/uL6Ywp5S2yikGeUTbS9ciCOFvLu4zkGm4+n
bLLkEmEwTL0pXMjbccg5iWFbZPM29mtdc8kxtXA2nmNWyFuiE4U8zewvI6bYX/yrC3lfYuxX
0Im9LbN620ZDzlv7SUWzOS7wWQVKLohQB/o39vg5sho4SD3AR6/xy6yP4TnlgT5eTS7gPOqF
Pfr5LDYOFSz+DPCGx4rcBry7KmhD4zxJD+iJs7qs9Xdpi8AKcB5kh3+Sv+YmFaAlNiVJWChW
ZWJB/cli0Q79OZsHWWKjKfoFpRFVUzXs2ugeK7yJsd9g8/GMTXj01V6paosAXWyn44u2hIiU
yQjwEpswbskx6SXMqgoPhGyye7k19lukEx59xkWKcRUDR4/4ZwR4n877NmM/1Cb5jT0rA5ST
v/LAD3iBD5cbJVkFrSbe2NNir6cmaN7jQB+W9C1FkQXU9G/wWbnnOl3A1qcLu0FQ8MxwrQ9B
8SQ+oKccPsH+kNduBo409S29XC72JsXGJTau27TWaHzi5iL2ayNN/6fYOHkDL7HRVKhxcRHe
ayHwZtM9DilTa78+9MQTNuHS1zO7cvU/u6Jhi4sDpv/N5t7FeZFNuDhb9916JzUm8Hm/ycWZ
dHKwvESHE2l4YuZerDHYlR+LfsTeHrF33tuvEdiWP8BnFUAlf16Ak0oDfFznxVQlLPQCfFbp
+TY0SQWHJC/w4eYBdf0BOvoP8NmrnCnsNNBWm4HeUdijyXGfDT3xLLGjq2gvrZQIh8D0RCza
ovUmx31LbKIXSkk4Syu9ZnQUeK0X6r+1nk203hIbTVo7xRxNzrmDg+e65dB/7u1nQ048C4Xw
x0lYvbh+bQ08+vBFOw6WeXawvMQmp6oS/s3MrqoIK7rGoh1sbHKuvMSGXicPqqWTSIfT/NYq
AD9S7w+y9qsK2tIN8OHKXk0dzu66wIcVnyVDj8IH+LDia2GXhc4sD/Th6xyN/GhqxwU+rfli
zBf1pxnoLc2E95qvjHiI8iy6o3apNSouhRhsj9xk7icTzbfGpsR8TlNmiiNQRs39tmQezw5z
19j4fotLKcrl5VeIKVjdcjQ9NfcrIx7iEZt4lJDm2qpJkYbGQ2wx93vd2PM77SEbl2+WS+6R
E8OdwROxvCfCeebut0bH9ZtvlfyyFPLnPehOTT8pbTsGR867+xGhQ2gX+HAnF6eG9sMN8OGO
PUnwAekbe/Qavzz7OlilH+Cz36BqauDr+QU9+umEMpwbd2F3iLvJTHAZgRDlWYRCa1x8lyEd
PoI6YO23Rias/UTMBUSm0sDWtli0Q9tNZoLX2MRMsD8auqpxVnRX64s2yIfZTHAZcRAP2eSu
pFLM5O22d87cL0+6BNbYxHhvuNeo/3ScDnhAcsDcb41O1LStdX/Gmz6YsPox99uh7b7N3A98
QF7Yw2e3NfmDDz27fYMPCzxLBe12GuCzEq/m5G9B7Mc8wGe/w0bJXwngd3iBD8s8Dk0Bmr9c
4C1VvPveqTJiIMqz4ATtzaUECfkfDm7ffdGOUIup0lti81J6ylmcVGYDy6yblN5kJHiNDaXO
ro1iSNNVBajCfdEWMTFTeiMG4iGbrEVyd6mXBYwI2mTtl9tf3mgPyYRkq8K9C5mF8TEq9PZM
ZNyf3K7RiWibKo1KN+EGpxmulSR/hN53W/t18LRmgA8X8cQ3qxnUeBf4sMbj1Dt6WnuBj5fx
cgdNVQb4cBlPUq1omN0FPl7KM/Q7HOCvLuaNMIjyMKijF+mZqJI10BNvm8Pf/TDkGhuXa8Jq
NUYh/b+oU9mODrB5NW+JTZj1VX+CdaMoUMJBHVtc5GYab6RBPGTjWihHwIVV1xKwyNth8Tfz
b15j8/ZvjhRhEtdTYGbkAYu/NTpRzYuQZ+YuUhiOrP6x+Nsg8r7L4k8baFE7wIfreZr8xYTW
897gw515OUlGLVYu8PF6XgcdDi7s4WqewGbiF/awznNxmUE1P8BfXcsbWRDlYUyHhsTjOLWt
oL3KLnu/WS1viU2U5Rr7yzfmVR7kdGxxcp7V8pbYUOpEImISfMDqeyzaISUm9n5lREE8ZJOF
VGsvmYuhgZ977P2mxbwlNu9iXmRUZ665gb6Ym4p5M3u/NTrh1Of6zkV45yZgXt4/1d6P/vb2
fo+KKmA5ZcMjcoMq/jbTQUI18QU+q4nJNRpsOXj4BqslMdhOfmHPXl0XDL6LQQsPA332+nJO
GfYZusBHP6HvEJIaOCE/wDsUMd3NvrpOGfkZ5VGqQU/ZsqvHxjWM4LAbt29pL3P1eu84uEgn
1WLUuzXRIuieKu3o0C0vBX6nU5bY1CivORXpRoTm+tY91TWye2/LMgI0HrGxV4BGo0ji8/0K
xsa2DI1PTWjW2PiLxX82JM1FfpzWo6XPLXbkPHEcXKNDyTpHh6nfb2wN9HpNa8Hrf7ok/nc5
DmZUDFzgs1rgdTgM3o5v7GG9F0YQ4MHHAB9WfIVTKWB56Df6/FVGDYfe2KOfT0tJuYJVnAHe
ofdsctI9QjTKo2SDltiVCvlrWCPNDiw6L04j/rcRTZscda/RSbVqjzG6XjMpXMnZUgK9VUi/
Ftlwspxd7HV5xeKibQi2QyH50/2vbrWPZ2zM7zRtxUVfFRd8GBvbcqe53rs7OvhcZOPKjWOQ
X52TEhr8nvf0muaJ59EanRgQ8g2L/0elGTwjtTYx/qP3/gTTQQU7gS7sYQEQrjeoRrnAh4Ue
+1YU9aK7wIcLtxbxZehZ00Cfvc5NU2voR7zAZ0t7KskUzFQc4A1qQmhy2D3yKsqj9I0er6xO
nXOpGR2p71veWKXe9mh+rtJJPZfuOiJiKzJ4dh+Lvrq0t8QmHrE5ZkZrya7ysQ3uttLeXTHs
96328YyNb2uFWEopPXcBz/5001DvJLh4jU30J1b2f3Nh6q73zs4oT/xnluiUsKCoRWrr6tcH
rYnbz+jKLqn3XaaDaAvrhT3c2ChJKppdfIEPKz5LndARyQt8+qi+Je2o4dBAn73OZnFvgR/x
Ap8t7vWexMCGhwHeovgmNnAjtKI8iuBoqTdTyiSi/jJGi3tbPLNrn3iFrNFxNkWLUWYxOEQ8
7TgBKG3i/bvGRhLnFtHFViWDI0ayJdmPpmXkkVnxiIwmUeZiORexDJrIx6IdCqlOxliW2Lh0
a1obUxauQuBxk6/aESgybW9cohNF8fBl70qs/tr80qL4j+D7VsPB6LFFy2YX+Ozrv0jKWcCC
zwU+K/NEUm2gEB3go1e55NJTgys4A324sVb9AQLOKQ3w0U/InRNX8KR+gDcoCZ65/Y68ivIk
RaCl7PJOI0iAXU5gvy1ftMPDZTrFssQmplgoq3BvGbWt3ORHU+/qYL8WuZA/YP0rYhffuWQ4
32HPmMStYv19n308YxMny520Ww8DQrCqx3t8FKfOg0tsoqpn2S8Mu5pyJY66Su+p6pVJAXmJ
TiQnZpesbK13PFr7HznC8q8xHuSOSr03+KzU45aKob5VF/iw1LPEymBF7wIflnq5JepoeupA
n/0WG6Xe0ISOC3xW6mXfR6C5cQO8o12P7g/WaMRU0LOYihbCiM04w7FxseiLpd4am/fAsknX
zK6LYbG3o9pqE7G3xob8tqlV1a9NEwGrrZtGfF+JxPM77eMZm/AmFxcSrXSRCj4j9xiah/r/
qzvtIZuQbc1/L06EqRawv23TwDJN3AfX6JTXqUgpfnGcFDgZt+ro9KP2vtl9sDS0XnaBD1f0
aioER4i8wYdlnm9CFZzIGuDDMo9aqlnhZNs3+rjM44L6+lzgwxU9S77/BWXeBd4h88r9aCSN
xAp6EiPgeyH2vXyrJJKtYMKo7XHsk9tusM9FNv7iMY2J1ZjFRQePYrZsi8y7N4VbY0NRTG+a
i/SIekFlXtsytjqp6dEIrHjEJmp64uox9hOKFsE2jZiw3A9lrLEJwSYuvqlRjvwa2H9wS8GV
70qUvxbpRH3Ost/DZhbBkWhR72cId4PM+y7/wV7AN9gAn1V7EiPrYNLEAB9u08uJDfUbusCH
1R6Hhxz4HrzAZ7/D3lJXsLg8wGe1XtFUMnhKP8BbSnr3Yxk0MivoSZKApt44m5hv5eNoDSzp
belqU5mU9JbYuGwTK66MXB/lnEH/mERbzm9v29p+LbKJAcfSVWvrrRgc1bolR5f6pHg8Mise
seHU40bzV4aQEFgDi0U72My03hIbV22+T29cI7imC9hBmTcJ8duL82uRjm+SWqnCMaFV0Dl8
X/NPlHr8FRaE4Pt2x5v2b231V8CQrgE+XGy01NDTiAE+Lz8Lavj3wp69xk1DT6IDt3vMjh+Z
OYo/1cDI+gE+e4Xzuy0V7b58gbdIz7v6gguCEaVBj/INeuJeq1TyTZqg1WdftMPsTyeuxIt0
kktP1lp7bozO0MaiLdrzbur01yKbOLWvrWXN0nxrgNWA98R3E936i/y+1T6esbGkncz3scqV
0GQ+2zRRMTH7W2PjKrJXEf/lcOMIO0G1544Q5nJr+vlrkQ6nWqlJFjW/18DiTiz6J4rPf5XZ
X+more4FPqsFarTHgLvuN/aw1qsxKQZqvRf2tNajVFDv9d/o83oPNZ4b4KOf0LQmQyMbBnjH
QewkbIxGpAY9yjlorimohf1LJ0WLc21T+2CdVIDW6CRhsyIWMxYwnbTjPKK023mEX4tsNFGu
pWW/e16VIFDv0Z6B4Pu8ExqRGo/YWJJeLZswlcqo19+O5/dc7i2RceGmFmf9xuKcwJb2vKcZ
Uibezmt0OIoO8ZupXVXhOvBaIeVH7v0JXn/Ys/GFPHycrKkWVINe4MMaT5KivjQDfFjHSwz4
ggMYv9GHlXxPKuDh5gAfruqZRFc12oJ5oXfoPJ60D46cCHqUemEpq9KrGtYMLUbbllTZIrcp
fZ+rdCJmU0ozycEJ1Xm6g43Vydt3iU3zr1nUxZE0jlcwOq29Q0u8YvTmt9rHMzaawsOGa+He
q+8s0Crllvzifm8fvsYmp2ocYcwxkKQNPGeKVVvOlCdjIkt0yF+XMYTmN1tTNGElFv0IvU1C
77uc/rKBiu+NPa4FekUHRi7wYc1nqRu4BR/g05ovIu3R8e+BPnud9WUqj4Zpv8GHNZ9fuyJo
t81Ab9F89+kKNLIi6FHyRU+SK1ur1JVBq5FYtKF+5JpvUnJZoxPuHKW3rpYVdIssW7w5Qmfe
v4eXyGhSYquqWlRbxR7NsWiL5Ju0EY6oiKdsqmu+3MyKojnquqWPhPi2Jv65yCbEmwskLpV8
t4TmTG+SfEL3qdlrdCj5jdaKZfZ/BZ0b9UfHj+T7v0dGTnv9Rfsn2gp3gQ8363HKCibjDPBZ
ASCSBD3AfWOPXuOSuSVq6CDGQJ/9DrUlM7BpdICPfkLhOMIEzzkGeEfD3mwueKRE0BPr/pai
0ayb+r/cQOt+X7TFz1knGm+JTTi5+O36yiKIWuVJ+5dmd1XKX4ts/PFFZjmC2lgbYWx80Y7p
Ct+V/NWd9vGUjYXXdiktSmHgAygW7SiEzTpDl9iE/QsTZyWSSG2D54K3eP3RpDV0iU7Utv1V
6Rskv9G0osMia82UPyLvzzD7qx20VR/gwwe5NQaYwHPcF/aw0rNU0GLUAJ/WepETi37EgT6u
9bQXXOsF+KzWI0kd/RIHeIOeYJ3MBY98CHoWqWAlq0RjdqSnoUWjHW67RWcGbEtsXLYR917i
3LMXMFwlFm3p1buP0FpjQ6n7VjDHzExhtGHeF22ZzZjNBY98iEdsOPVX3kVx5cVoHyVvmUCn
MskFXGPjqo26mYVLFsWABqr1tghxnoygL9EpcSTdsr3m0HtDN0lr5ckfrfetVn+UTMBAggE+
XNCTxKir0gAflnm+BxXUEPMCn5Z5nHxDDcu8N/qwzDPfQYCF2wE+XNKzpGjz1AB/dUlvRETQ
s/CO0sKZ1iL4qYEzuJtKenorWj8X2cQpg0uiLMRhXQiX9HawmZb0ltiw77BETFou1EF7at6S
qzJ3+hsBEQ/JOJ5ZYk8hHewW9kU7ZNG0orfEJmpz4sJIS6PWrWN32omK3hKdV4trWFRJ603A
mNbVFtcflfdnOP0ZOAZ/YQ/X81rKjPYPXODDTXph3QfWRAf4sNQT/1vhxOCBPvsttoibQs1M
LvDhip7vdAp4SD/AX1zR4xEQwc/COyx6MIpmq8TgVt4X7aiBVb3vlV9jE3ECzXopPVPODP4O
NyW13UaR/FpkQ6kXyq4oKjWXe+BJiy/64ooej3yIR2w4+Y5Cq5K/NvzKo8p1S31yltS2xuaV
1FbFdxX+ACqgG/omqTdL411jE8G6WiMkhsQaOBrti/6RUu9LnP5Qw4stVhd/Z68/3w3iXn8B
PitBKaea0fmBC3z8UFkF7c67wGevctOesoHnbb/Rh6vKNRGBacYDfPY6Z6n+1EaHwAd6w8Nl
NifCI76CH2UK9BSvndy5NqlosGD3H9cOFTrxgFmkk4R7sVrIuDMd9YB5WQzeaYMlNi72u/Yi
QsrS4SP/HaMIdFs9/X2nfTwjYynqpr7bEfX9AZhVaHv8mUu9q9B9LrLJqVWhLpFk45oanK/M
e/wYy2ROZI3OK1OAxUrlahlMsVk1g/3TVei/yvKPGtgJP8BnxYByTDDheXcBPlx3lHhKo8PB
b/Bh0dcyrkt/ow+Le4tiJ1hnucCHRR/VlAltVRvoHaKP7vrV/FU8ciz4UbhAS71pc52Ua0Mr
KLFoy+BIuaPzuUoncrG0+ZtY/Q0GJj+s5mI9mA5eY6NJX5OnTNIN3GPEmi2i7y/vtI9nZCy5
FM8uXruGzTNq/LdmOfLA+G+NTfg8Nyb/x/9TFLSiPeDzvEaH/Xu2XHN5TY10VPStvWB/RN+f
YPxnCr7ABvisCqiUCCyBX9jjWq8wOu9wgQ8r+uq6ozVQSA304V6CnnzDDH7EC3z2OpdwOUYH
wS/wlvLe5ORvpEbwowwMS/50Fw77sgrasb3W7BB6bXLGvMYmpFGV8N31W7egQm+HNip2m433
a5FNS/4My72LXxkBY5Dblmi8qfEfj8yIR2TCw6+T/69EdQ+0UPJFOwI9qE2qe0tscvKbV6o2
Lp27wQPCa6ey/2P8dz+ftEaHUlX23RHXWmoGO1dj0Y/Q2yT0vsv4r6A/xQE+XN2rqQt4O76x
Z3WA5pTRdOMBPq334sAHNnu+0MevchH0I17gw7U9a5EWg/rqXOivPtAduRH8KAWjRzWscs/m
CgzsXItFW7yr2/345iKdcJez7lvR7AvBqIWyxV0uZOb9i3iJjaZeqyvJViq5vEBbPnf0sUyd
/3gERzxko73n2sSsu4KFS5U7qmHcJ5pviU14+MVpbm2u91yTo85/uiVAuP3lrfaQDqUYrI/h
q9qJ0dSsxcfAj+b7buc/+Ij0hT3c0MWpVfT48QIfbtyTJApWpAb46DV++bt0AlPHfqMPq2WO
zCrUDeYNPvoJRXqqBfwSB3iDkJiNCfNIjeBnqREhkmvzp3vrmbAtVCzawGbmBrPGJoxdLEJo
ardSFO3aKxtmUcsrvuvuzbvEhlPJoiX7vUMqYKNbLNpxSHjbg/j7Tvt4ysZqTKLmbsYG+iHH
oh0i77bz4XORTbjB+M4twuh8V4H2u+Y93tvldrP3a5FOSa00qaStkG+O0B9O+znB3SDyvsv5
T8GT+gt7+AS3phhlAo9w3+DDWi+Ot8BPOMCntV71fRjYlvkbffZbbBxzF6BivsD/xyf8DwAA
AP//7H1BsiU3juSJhgYQIEFeQGaT/xjds5jFdC1m7m8DvBfMhdqC6cHi509JX2al2nik0iPi
BZ0g4L6i9UqiCp7cDPAGPTGdEx5xEfIsYKErixBbdVkBDrPFRTvOcG8na38ssgnDZuauzTQ3
MbDkusflufG9Uccam5x6Ew2XjmzCaI077ehdnc8Jj7SIR2wk+XfEqcTRZ7YCzwnvYCNtMie8
xCbamHspKhIWNwq27fhVe0Y0fvmqPaQTRe3WumZXroIGQn97wvwlnf/C5A0dy7jAh0t6mnpG
Dagv8GGZ53tQQj3rLvBpmRcNuOgJ3UAfLunl0L9oSe8NPizzejIBhegAf3ZJbwRGyMMwj5aZ
oyezdAbPBrc5/01KektsoqRnRN3YGlwT3lPRe5nZ3S29S2T8C5uLkIrFHC44LyNb2Eyd/2TE
RTxk03Nt/j/uLvQ6djK4yfkvl8lMxhIb12v+4SHpEYVTUZfSXRW9mcpbosPJqJn//v0rUPxb
gFb0vjN6N6i8r3P+AxtbBvhwTa8m1NP+BT0rUQolJXgm4w0+LfTCxgC2C7nQh+t5NTVBj5cv
8GGhp4kIfA8H+LPreSMtQp4meeRWc83+/2gy96YkjzJzY1tiExbPxapLvZZ7BY13d1k8zxxX
lthk/7zGql6oCwmhXVNbTjun9bwRFvGITVj4sRYrvboKBxutN/n+iU68fZbYRGWuULX8miVW
cM9He5KG+XY062ORTsRTq5VG7EIPnb5dzbT+aqV3Tsf9n3/917/+37/+63//x//4z//1f//j
6BKFvZCnKzhg7WbD53iDBv8K60OtlgoY0Hlhz+rvTKmhKStv7GEFzik8EUAF/gaffcIWk4Zo
PMgFPnoPK/VEBroIDfDZp+wLur9aqLvlQG/4rHCbVMBGkIc8y77gklvLwtpctqLGF1u8qovc
sfmxyMa3OtlqZyOWQqCPuG5JGuZ2m9f2scimxe7IavP9RKtimAJvW3ZHmeSunPfzTfvjGRtO
xL35hoLCBgd1Wko75jAzlUn35CIb8VctGh2Kb/jA3pq4aIsAvztw+Vhkk9/dDmQx4K1o+MZi
t8NXC/Dfq9T6hZ6HapLUwGOCAT6r9zQSOEG998Ye1nvVNTAYTDjAZ59xywk9CbqwR+9g6cX/
m5hgvrBnn3BuNcEuHj/RO7ReuT9W15Hkoc+yL1yFVhbR3nsBv/Jx0Q6tN5lfWGXTqPrviXIB
l1/ZEkrCrw3ozfK7RqWlzFUyt2KlVXCEyS/aIo0mQk9HjMcjNi+hZ5ms+FPP4Gu2Segx3xf1
V9nk0sT8DyaxAqZQ+kU7Kq1y6030scgmJ+PKViNiRTocz/09JbNL6J09b22NEil4ljnAhxVe
TtLADccbe1jhSSoCZ+m9wUefcZGXvTIooS7w0XtoFEOQ4N9wgA+3yIbtC8N5NRd6R/Mk3Z+p
60jK0Gf5Beoqr9eau69YDT3p3GN60++tSNbYaCqRLNGktF7R4I+4aIfQu+13+Fhk01OWpq71
qPbMYEubX7Qjry2Xe38lHUkZj9iE4Yt19XesqD8b0G2c9hh0zyytV+mY74tIaqvNfB1E6bQ9
Nb376vEanTD7ZCuqJgbboq06hH5Lvd/E6bC1mjSDPZQDfLiHUiMxD+2ifIMPa76eKmjvcGHP
Kj7XwaWB7QwDfPYMV1ypV3Awb4APn+EW820t+JAv8Ba9d58roSMkQ59FF0i30sl/yI0YzCV3
vbclte7WFvDHMpteeiNzmUS5g6YkftGWmWialFuW2EQ4YNhlx1RisYqe4O5IFHS9NynsjZCM
R2xCueUwWegszbdo2M97k97z/+6vXrXHdMxVV+cSmXXUwJ0SLQ6Y/Fm+TtKT1+hwKsK1S3fl
2gU9k/KLvvXev6v3DrschkF1Y7AmNcBnNR5rQktSF/ZwvUeTFTBoYICPPuPcKClW7XhDj94/
IUkM/vUu7NlTZbPY/WK/kAHecWab78MkdCRj6LOcjy5WjKl213aguuNNjjezat4Sm5zIFzWh
StzEBOvPi4s2sLFbV5WPRTYuO3t0snX/xnIHT1lkTygx00TdjWSMR2xcp4lEqYiVhRkckYmr
dtApk3PbVTpNfVvkgsg3FBk8VI+rPrXf8GORTrQOqsavp5F2eLZsrd/wW919vb1heO6CL+0b
elbgiSUS0IBtgA9LvJ4K2DN9YQ8LvJJaRWdZLvBhkUdJBCyRDfBZmVdaQpu/LuwOkTdJj9CR
haHPkj06M3Vfpojr64/HRN6WMehJesQaG9drZK1ko1p6LaBDa6ItvXl5cmS7xEbCJqn7/wqH
TyNakLQthje3I+o/37Q/nrEJuWaWi4SBphJok0yLo7Z/bmezyZHtKh0jYnZOJU6iYV/DHeF0
972GH4t0OGX1rRGRdFIydA56be3/Fnlf6GsYLru+S0DjF97gwyW8kjiDfe8DfLyIlwXMWhrg
sxrPLHpKwHt4gY8X8gj9Gw7w8VKeGXicMcA7WtluG3J87R1hGPosoaDnSlJdEtUiHe0k32E2
x+U2svfHIpucOCIea9EInW3YrzBvifaYl/KW2IRHUmkk1CoTqiN0i2bNWe+HunVkYTxiE5Z+
/oIR+46MSu9wY96WEYw6UXmrdBo131NElV4JDLveVcqzyUHtEh0XbN1cf+daO5x2/V3K++v6
Gmrxrzj4SXlBzwo9pTDaBD/gF/hwPx4l39ijMxhv8OFiXk2GFm4G+OxT7jWxgPnSb+zhUp6l
IuAAxgDvKObdft598R05GPosnKCH2TMVJlMWdPyx7xBGtUyapFbZ1Kh/9a7hlIy6V2/qx5uc
oi2xkejVLS5YWy9+r9ATW9vS4T87sR0xGI/YRDFPpZNrcHJZBPrmbTqxnZkaLtMJ+z/pLDVT
BfNwNpkaur781bv2kA6/6g0vs5uqFZZ5a45qv7vME1jmPekyB/vLd6wT26ZCvsDQT7EPw4U9
XGWM8QlwUGCAj4vPzGCc5Bt79gmHR19Bm0Ev8NE7WKsmX6cw6TDAZ5+x9I4Xan+id8jPiaGf
joAOfRjQYWImXaPUCB7wxUVbGgYnmmCJjabIdi7dl1BmtJAVF21g48v9vSRYYtOTcCssrUlW
0PTAr/l0m5cRz/GIzNvmhWp3JdhzQ8vZe/z8buODfyyz0UxdOHNW7Wjg6JYXLfphf/WiPWST
UyRU12hONetgF1Re7Ez93bXnP8rPj3PHxNQAn5V7JZq5Caw1XuDDcq8ksPX5DT37hJv/SA1s
uxzgs2Iv4kYUDHgZ4MNir2myDN7En+gNguKVbHC3Bo+MDn2WahGDISLKnamAq5ZftKVx8Dbw
68ciG02swv5CSMm+xKPuzVuO+2fuzWtsWupkTTTsIFEDqQPmzToSOh6RCd1GjTTy2Oywpx/J
xDpykY1U13k10p1zhfvsduxKs9zukT4W2eToKzHhatm/VmDZNC/2lXyLvS/39LMe7R2gw8sF
PnyiXJN/UMHhkAt8WOXFoo4Gh1/go0+5iKashrr6vcFH76GVlloH+wYG+PBT5pxgU78LvKOo
1yfOzSMJQp+ldPhC1UxykxapbKjHy46UjqqTM+UlNurKSNtrErjWDM4y6p4T8n7rivKxyKYn
MwmZ17I0Ah1r4qIdrYOTRGQdSRCP2Lw8/cLhpfiGQitYOtrm6TepHy/SaTVbUW7+y9EMJjzH
VTtO/G+rlB+LdCLduL/SxBs5JVSGf9s3b5N6X+bpJ9hH/8Ieruq1hNaYX9DDKqCn1kBHxAE+
q/WUUy1g0/kAn63qWcOTYgb49DF9T9zB4vdP9I6q3sTRr4w4iPIs2cK38c1XrW7hTYZRChvA
HVU9utOuPxbZxNbEBYVIbWRo8OAWy+P3HvRmAV4j0/3j6lcUarlkAVuS+5Yg+KmhXxlpEI/Y
hGwLmadRP5YK5m8fMHBepWMxWFXJv4/dty2wod+WaeDbcvjHIh3XbeTP3NhfNt9aoAfsa82q
32Lvqw39CprSdYEP9+lJygJ+vQf4rAAIlz4Dj5YH+OhTDp8+AQ8bLuzROyi5JKrguegAH/0b
lu6bGwLbfgd4R0FvYutXRhBEeWbO32MQ2D/wUZWAE++3CNY6seFYY5NdrhWpalJiawJOGW3x
rOJm9we3a2w0MfeY0m5UxUALrrRjzzidESkjBeIRmZerH8fBrbIaGO2+aUTEb9+vXrTHbEyU
skQtnCIbGVV4W+jcnkN/LNLhJFpNRdm3ewL6qfpF334vGxTeV5n69dd7BNr6Bfjw2W1JOYPt
KgN8WOj1l9M57uwnO9IvHlr71Ypa51zgw1KPUkQ2gVLvDT4s9SQVsL5yYbec3N5b+5WRAFGe
ufJ3jkEMM+6GGmZusvbTyTjGGpv86tDLmmuuHRd6Wzr0ZqYva2wiNqSXlkU7a4PrrH1HuUhu
66w/37Q/nrEJ0ValUNhRd39A8MntjtrkLJ1jlY69BmWIfQ1UAYN3d6VzTPyb1+i4ass5NxFS
KQx6hfPi7M+31PtSaz/1zzfYnzfAh4t5vl1t4Ds4wMeLeaDFeSDPqrtXSyU6snyBD6s7f6kU
NJcc4OOFvELgN32AP7uQNzIgyuN8juaLbqSWFdwfZUshb3aCtsQmanLczLd0Fv9G5wY/v5C3
xMY/XBFo4b8/i3+jpn68JdDidp7k55v2xzM2Yc/XtGs2o+bvG3xYu4NOngT9rdIxISlVuvjP
Eu3SPVHKW6ITpTwyl91S/Q8Hs+Tiom999+/ru68x9ctJM2zr9wYfLuVZYgL/hgN8umkrNbCI
f2EPF/I0WUOjii/wWanHJfUKNjcO8HGp1zo4lTbAO9ryJsZ+ZSRBlGfu/K1Zka5RZmngeKpf
tKUtbxLFtsbmFcXGLl2J1AwcKdkVxWb3ZmtrbCI2uLrosixF0PHzPbHBc6k3ciAesQmp53uy
YpmalgZGqGw7tb0ft12m01skfEeDgLgYR6XeDtvFaSlviY6rtgjYLU5Fe4eHMP6epbxPMfZj
9Jxkiy3DtuGQ89Z+WkHPsgE+K0Az+QYHjG4Y4ONnyaro0MAFPvuUraZwQ4Xt/QJ89B5W171i
YD10gA8/ZWopM9i9+hO9o944sfcrI6iiPAkPkOR/Zggoy1UZHArzi3bItsp3bH4sstGIXZQw
4ZYWLYRghW7Ls+m3kbMfi2x6mBX6R7b1RhU0kep7LORmji9lpFQ8IvOy9ytW/ZvSI+nlpOML
86TauMgm4u6IqZBTAg1x46Idz6b/8kV7yEb82WTN+kq9y6BJhCym1fzuCvQfZO+XU/cvDCgF
3uCzgq+Gtxh4rvzGHq43amqGJsZd4LPPuGXf9qL5Uxf4rNyL6V4GQ3cH+LTc6wlesS7wjorj
xN6vjLiK8iyugtlvoeZq0dSFVrV2/KqmXs5rbFz5N3IuUql0QU3p044GaG63wSgfi2z8renW
JI4SSziCg2pvR/7dXO2NsIpHbF7+flVbbC5U4UmETzdzXmWjolr8AZWo1KFNGbolF4XutOvH
Iptwce255AgGxntu+9LP5lvs/Q72fr2CVq4DfFbllZy4o+2DF/i4zmNGE1Yv8NGnHI59vmiA
li8X+Og9NH+1UNvaC3v4GbPFMRnq63Ohd+g8ulNGvvqOXIjyLLMjxgBzby1rbYR94v2iHZkd
9bbt7scim5KoVKtWspXeQEO8mCbfofPqfVrrGpuemvomSyOBVtAhEb9oQ0vk1N6vjGCIR2xe
9n65aw7D65hIOun4ImUi9BbptFZq0XA/ZmVQHNGWnoypvd8anXDqizplL61yVVS3ftv7bZN6
X2XvZx2sVwzw4bpexUMdBviwGugxRwN7/PUdTd4PLf60g20NA3xW73GITExNXdjTeq8lzugh
7kBv0XsTg78RDVGexXaIf+CNI/mJKuhns8ngb3qIu8RGQ72Kf5TEFB6B0T3qderwt8Sm+09P
VJv428O9Y5+UuGiH3ps5/I1siEdsQrlRzZRr8adTwS3xCYe/RTq+Oyqdu0tJdW2FDo20HXSm
Dn9LdMLOmV/zL67K0XeNF0ecv/XeFzv8dYWHgt/gsxqPIxwdjWa7wIfP9TQZOsY3wEef8su1
D1zOL+zROyjimwcBW/UG+OjfsPTIOwUnbgZ4R6PebDB4xEKUZ1b9XapxqVECa4R+2/cMBufJ
wrvEJvuNrpwj9K1VATuO/KINu6z5YPASm8iMI4rm/ZLbg8HgHU4pQpMugREK8YhNzH1kF0NE
OdQ9+KrtmhaZabxFOlYpuxbOvfruCPQ9jqu20JnsJ5bohF2fUKEsQmagK8+3x99f2+Ovok5f
A3z4ALcmEjQo8AIflno9lYomd13gw1KvJMugk+MAHxZ7rtHB1uAX9GwbIeVUGpgeN8A7hN7E
4a+OSIj6zKY/HP5yWAYraUVbp7Y4/FW9X33X2OTkCqUUFpOIAEPHgvMOoTdz+Ftjo4lya9qr
hQQXbPH1i/bM0d5vKeoIhHjE5uXw1+JknZoVxoXeDt1K9f7wdpWOxSi9+earWFMwBzCu+mSh
t0YnzFyEa42TW+lgQ+i3A8xf1OHPvyiYOhngw8U8TU3AMYIBPl7MkwweKQ/wWYVnlmoT1Ofv
DT5fziM0sOMCHy/nFbDeeGG3aLx7Q446IiHqw7iOrETVhVEr4ARWXLOlP+9+FnKNTJTlcg+T
Mu241fvn1/LW2GjiomxVOpHLVjRfjrf05+l9f14diRCP2ITzi2rlVyhEZYadX/YMYkx2E4t0
rBi3yllL5dJROp9ey1ujE2qt5Z5bLt0UjRT9ruVtkXhfZvIHFiku7PFKniqq8y7w4bYtivoI
WMm7wIcreS7QO+hFPMBndV7uKaNhRwN8uJonydCK8gBvkBN6a0vrC/DIhKjPfPpbq3Eq2Atb
Bq3KNpn8absfuV1jkxM3ruSLVW+dQcvCuOizq3lLbDSRa3BfglnMtzJwNW/HyO3M5K+ORIhH
bF4mf9wiBlBiVBVTE5uObUXup35W6VjM+5iwuUBCvd0P+Dmv0XHVJjF3X6yXMN1Gpd4Sm99d
6uXPMPkDm+EOt8Ghw+I7zqI2yOIvMx5EbV4G+KwszpQauD5c2MOimF2jwT40b/DRZ9zFNVoB
J9AG+KzkZEoFHJq6sIcL3MVSJjS2faB3lD/L/XxyHUEa9Um4QU1sWmuYg0g37HcV12wgU+R+
XGWNTBzvmoviVqv6lhi1odmxK+Wu9yMEa2x6nAlzjmNuJmHsbeubQt9uVdfPF+2PZ2w49W7G
pZC/a2gj9R6Bf+8T/WOZjFD1F0191xJDHqiE3DGrkm9NvD8W2YQXlTkdKb4gZXAruepF9bsL
4n+W5yDqRjPAZ7WeShzOoSknb/BhtVeTCnrUfYEPqz1frdHJzQE+fJDcUjPwrHKAzz5laezL
KmraMNAbRMXrCPduGR5pGvVJwkFJvamwkEiNJQx0cNnhocQlT9bhJTbi+7uWC0vtrWdQvvpF
O867+60W/1hk4692mA6qRKJdBkvubQsbF3yT8+6RpfGIDYe3nUSPpj8iI7h5dsOblpnvCtQ/
ltnkWl1JZs5MhVE2eUug9K1f58ciG1/MnUimzj33nGHjwW/Ft0nxnTceLGCh+8IeFno5ofMW
L+hhkSepoHGAA3z0+TLlmozRuL2BPnoXjUoqhn1pLuzhpxyGm2jL5U/0DpF3GwDnS+9Iq6hP
QgRqqi6Ss/o/RYwwSn7RlpPuSZzdGhtNpZfapfTufzpc1asbSkcu8ibFliU2TCl38i8s+dpb
0BpyXLSjEtYmI1Ijr+IZnRQ2kxL1bdOXARGki3YUkOdNjUtswoTGZZHlVriUDH4M4qotD+fe
dHD14UQ4trUe3oMFDILkRTbfMu83Mh2sbNi7O8CHexs1KYF/wwE+rAZ6sgp2ugzwYc0nnAhc
2wf47DGulNQKaDs0wIefctYE+1D8RO84yNXJBOkIrahPogRqcq2XqRR1wfdqN4Q0n25Q2fOT
3CU2EsWjVsOIimIlBgt7W8qUr/aSu3V4iY3vqKWLSLHmjGCj6R0TUznftgP+fNP+eMYmJJ8L
JP+xRi4zbHuyo6/KyUx2F0tsKLbCMW3vq2DpFWNDi8bM/63oOlF8i8/G4ni9S5ZXvN+3zfQx
xfcFtoMtg10hA3xW5bF/kMGy2YU93MalCT13vLBnn3AuyVcN8ID+Ah+9g0KSWgdbCAb4cCth
SzWD7UYDvKOmJ5NGvRFWUZ8ECLwyH0tTKaLdwJajvMl00Car7iIb6l3jKNpFXgHfoLwlYo3t
NnrjY5GNpmzS2PWQ9NIVzTrecjjIE9PBOqIqHrGh1GsM9vqmu5MxaHcSV+2gcxvd/GOZTm01
Wy3MOTfQxIm2FMMn+Xcfi2w4STei3lx4W4UFnn6X9DYIvK/yHMxoNsIAn9V5YlEWAb/hF/iw
0gv/EbD8/caefcZCiTJY5Rjgw0rPN4mgK9mFPdxE6MtpQUNYLvBn67wRUlGfBAf4Rs2KKrew
yc1gfdcv2sGm2mTxXWRDbNIz1XDJreiU8o7w2fmU8hKbqEpKjI02LmqgzouLdlS+aHJ0OyIq
HrFxxVa6dOXIoO4KWrJu0nlZJ1PKi3SqCZM6pYgGzrCF4paj6FmfwBIdDls0a62HJC5gPf/v
OqX8t/ccbGio/QAfruSVmAsA16ILfLyWpwIqqAE+XM0TX9nBE+UBPl/NQw9DB/hwNa8nKmDN
e4A/W+WNmIr6LHSjixr7ShUTQWBPW1y047RWJ3a/i2yYpClbztYF9dU8UM1bYuObg1ZdthYp
rXOBq3k7CkZTlTdCKh6xCZUXESIqOUvLcExc3+GiyHXicLlIpzZxReS/yZhUg0Xrjm9pJqFf
vWsP6UQ5j01blPIMbIjixbTIb5H3e7gOciew0nOBz2o9pWRgXuGFPdyzFTtQNA74hT2s83pS
dBRjgM8+4W6pEqrmL/DZal6TZAQmnAzwBi2ht91F/7PbSKmwZ5kbTf1nnKO01lzxodW8Lae2
eu85uMYmRjpZqfk/2W856Py5pf7lOu9+7V1jExuYsP1WqjWGodHh4c+u5tnIqHjExr906t+6
aDPkJi/76nM6T/iXr9pjOjWqrNxYmJqBXTB+1RZ7abvfU6zR4Rj6aRofAukKC721PcXvLvTk
MzwH0R6fHV/WbfMh5939pKENZRf4cKGxR3IQeJR8gY/Lz4y2cA/w0accJi7ZQHk3wGfLeFUj
BBss413gw09Zw9sfNO79id7waeEyEQYjRcOeJBv4A3ZJUCXsiNlAF4C6J/at3DpX/Fhkoyms
e80VqIiigyFR7t/AZjYMvMYm5norS4tWLieDzu+nHeHnU48/GyEaj+iEX59kaZSb/xstImwy
+btttfuxyIb9VcthFp+1toIewO6wzsh6uz34WCQjriXN96K1kVVDOxfku21wl9L7Gou/eOyg
Pd0AnxV8UeJkMEZsgA9LgZK0wSknb/BZwafhrYr6w17gs4IvpmcETQS+wIefMluK0hbq2/1G
7zhbnmTJ2sjSsCf5BjVRaaU1i3R68MX1a3b4FZZ8PyiyRkb9PlcrXGPmlNBckB0RcNzypOK4
RKZHZprVLF3C/gWTFH1PZNpU7Y0cjUds4kMSSo+bxAsHV4P3DFbcW0muspGas4TZXm2M2kCl
Heb9LvfuoxPX2PhSTkVb9tetUwXD+fyipb73b733Wxj8GXisPMCHj5XDWhhs1xjg0zWfhPaT
XNijz5h9a51iMA91fHmjj95DKy1VBWuPA3z2KVe1RB0s7F3gHTJvYvJnIx7CniV3uC6qteRs
bBkcv6pbGqH8vtx376+x0dRJC4uF/QqBPnJx0Q6hN0lUWGPD5G92Y2pKjBuHx5nnDm00Mfmz
ERDxjE6ExBC5QGJhBTvVt5n8TUrIS2wotZpLFqFeGzFIJ67acrT8y3ft8cNpliuT6z3xPQVs
8rf0cL6l3m9k8sfg8ceFPVzYC2N60MN+gA/rvXDwhY/43uDTiq8lQy10fqLPlvYs/qPoWe4F
Pqz4RBIVtII70DvOcicmfzYSIuyJb39NGtkQRSSO1ypYUE1lh0oqdFcO+7HIRlNW7bEQl0hk
RucstqS1zY5yl8jEqWzktbTsy3ADV2FarLg8UXwjIOIZmxTDPMVfsuLaAjRNOWDrvMaGwp6V
yHftYkUymHrjV+2gkydj6KsPJzJVSmlF2Bjdyy42FX8rvi82+avwuMgFPtyxF8slONY6wGfX
/9fENLhWDvDZp5xraqh5yQAfvYeSSzimoLHeb/DhI+Yw2UVHgy/wjrreZDTYRkCEPTHtD88+
M1XqEd7BaBPVjj5+X+gnS+8im6zVlbBari2DNhZ+0Z4D3Mmx2hIbTerrrss8omhCxNj4RTuO
PGdGfzbiIR6xieE4zf58XE24QAI/kZsMYKhOSsiLdCxm6k19D2dNcJW3JT+P7yadPxbpcFL/
OToTZiJc5el3XW+Dyvsqp78IsoSd/gJ8+BDXV3bwE/6CHhZ6ca4NSoABPvuEhVNHJ28H+LDQ
e00ygDrvhT0s8ySheesX9rNF3kiEsCc+/WHYZ1X9s86+3WDU/7jtSGgrPCnkLbJh10UsufUc
Phao/8sOkTfzf1ljo0nIxZZ1l6zSQR85XeyVfyLyRiLEIzYvB4R4MMKiKoQlMG4SebO4jlU6
FrsU/12XSrXBdLbkdczsnNfouF5zzer/ZNZc0DCCxXGmb5H3xS5/Bp4LXNjDhTxNmdAD2wt8
vJAnaNzQG3u4jKe+QIPbzgE+XsbjDvqqDPDxMl6voHvOAH+2whuZEPY0r0O6b9275t4U9cTb
k9cxO0FbZJNLGK6FLjIFh4hPlPGW2GgqJGLacwsdgZ487zhGnzu/jEiIR2zCw6Xklo0z10hk
O+rjLPcOf6t0zNWdmPXSSQnscTpRxluiE2U8jmBG9neug2EqcdG3wvv3Fd5XWfwJgR1RA3y4
jGeJ0R/WAB/uzaPUBPySDfDxUp6icv6NPSv1XKF3NDf1jT0s9FoiAlNq39jPlnkjEsIexnVE
HcK6aRzWYuWIvKWXnF+pAHdr7yIbao2pU2dtcB2PdlQlp3W8JTJhyRyztmZEmUF/v011vKnK
G3kQj9iEypMeQ9AccyXlqL8f3U7I/FimU191SVXmLgZu613lfa5XzMcinSjJ5dqouQCvqFvh
37WO9yn+fvBI9pZcp23DIecd/ipaRh7gs9ozUxLUt2uAjx8jV9SdboCPPuUw7Wuoj+MAn1V3
TVOpYL/gAB/eYWhNFa13/0Rv+LRMHf5GYIU9CRGoKfvfzX8nFCkCmAStWzzkuPKdavuxSMbf
BYuOQbZaTTO4w0o7+hC45clUyBIb9g+YlOxKvWspqL2QX7ThTZtbvoy4ikd0XgZ/4vsxK/6A
QNG2yeDvvjT3Y5FNVNmkcddamxiaD7pYmnvi8LfEJtz6LE7F1QrqVxYNMn9HBfqPcviTBnpf
D/BZwVclMaHpwBf4tBRIrYIuiQN8VvDFZA+4eFzYs3LPeoqqBDgE/AYffsbSce/zn+gtcu++
5NhGbkV7kiVQU5QZ4mheLBew5Fj3VOlmhs5rbNRvdGHnUomlGmr8shaB9d+MX+7rQGtseupK
nKVUV+OopOhbTv2ncq+N1IpHbF5WoZlcekW/HajFtzn83fs5r7JRUZdGuWfO2K9mtUL350Py
21mXj0UuknLhVpxPxEeBB2Wy2I/xrfZ+B38/Q8NjB/iszCs5+XcClHkX+LjMYzDd9sIefcYv
xz5Bz6l+oo/eQ/NXS9BgtgE++5RrLalldNx7oHecLU8c/tpIh2jPkjsifUBz7tIy2g1RtxyR
8Ssj4G75XWJTEhXNLiBFW+0gm7hoA5te7g+X19gwpUa+ma5GjQ1s73xdtEMbTfxe2oiHeEYn
sYmYNRfjvns86vciZaL0ltj4bW7Fem+9OakGynDaMl41dfhbfTiti9ZCYS1EuMPf3zI87h/l
8BcNErDFX4APl/ZK6g08lx/gw5qv+88Arey9sKc1n/9HGdyMXuCzio+j7x1crQf4tOLLqXfw
Hl7gHYW9ibtfG/EQ7VlwRyEhI9PSmzasFLbJ3W92kLvGRlPEZomRdpdIaF1vzb7iz3LvNvn4
Y5GMKzcl0ghTiLg2sIs/LvpsuTfiIZ7RCbnHxvldQTps6Hw/nLTGJlS1P5bSq/YiDWx/8qu2
eC/O5N7iw2lWsyn5vzuh5uFprVzxLfe+2N4PTWq9sGcFHksMY6EzwW/w4WY9jdkPtFnvDT77
jLMlApuyLuzROygiYamAHSC8sWfPlgsn6WBi+gDvKOdNRkXaCIVoT4z6Y7jXv+xFetHwPT5p
7FcmzVOrbISUa9YmNVQEyGbHdMV0IniNTXj0WeXSokmPC/hz3TMRPPN8aSMS4hGbl7GfdjZy
PeSLBmZhs2ki+HX35q/aYzpW/CVzMWQh7Qmls+NLOp0IXqMTHn1MTsSlcOcKTwR/G/tt0Hdf
ZexXCfX3vcCHT29rIkWnMi7wYaHX47bgQxk7fLAfzQPnlOGp7wt8XOg1dDRtgM9LvZJB85cL
/NlSb4RBtCcO/WHv1ylrjlnailpm7rH3qzqpryyyycKmufXw5UBbef2iHVLP7kN419iovzbS
SSjn2ioYpxgXfbbUG1kQj9i87P18O5GtxjMCk163eThPTm4X6YS7UOFcuXNj3MN5SwMl3ynX
j0U6rtpKZM28dF5Hh838om+p929LvdP2fiURHGJ0gQ8X8zQ11OxqgI8X80TBUs8AHy7mRUMS
6Aj7xh7WeJwKuEBf2OMKrwoo4wf4sxXeSIJoT1M6tPpmjXo2NGtgl73f7Zjqj2U2uRuTVslE
qCY6UcxbYqOpsApV9T9b0e6KuGhHM9vE+KWNHIhHbF72fixNXOB1FrA2eULhLdIxLdR77lRe
svW3KeYt0YlxYN8ZURcXq0qfO0P8rfB+B3s/Tp3RSLYLfLyYpxUs9Azw4bY8/zwRaA8ywIfL
ea49GuoZdoHPSr3ckyp6cHuBD4u9qHKCZe8B/myxNxIh2sO0jkq1qmVfgdFEiE0mfzox+Vtl
w03Yly0pWQlsMI6LdnTm1Uk5b4lN+Lz7iyOukHwBRptp0o4v3lzsjTyIR2zeXs5SpISoKPXo
ye1rsGv+qj2mY7n1bq72soQP8lkv50k5b4mO6zaVzJKtlGLgLycu+juKvfyXd/l71GQOtpdv
+EZukMZf5T2oaLb2AJ8Vxjl6fkHZOcCHhXE0WYMFvAE++pSzlggeBJXxT/RZ4ck9xcAcJjwv
8NnnLKa+LPz5Qf9/AAAA///sfU2OJTmO9IlGEEVSEi+Qi4hTDPBtvxlg7r8Y8j13b2AKrjRX
KpRZXdENNHphXhV8cpdM/DG7W+gTvYIc3855OGU5zTT6I4ODkBIk9oOR1Qz0DqRF+oNa7r3s
5sKRRJECbc2aOm9B+SQtSYXqIBU6FY2lbKStVqeVnUBFb1uiFeS7++AednppPIomfMVNcnN+
DDvi6pIXrWQd5NyngiG/g9TStfmnw2jh3h9aQY3ZBkMrU9FEaSNLtxIi+ArKbMzWQ/50avyP
kh8UBSu2J3gv5xP24x1lKy/sZsYXg9uofsQB3sz4OOw30DHvE72Z8dUkGbx7nOCtf6FFjhic
Gz2wK5KHPJhRPk01+iOjA03qJM+ol9YqYwkdf6iu4Ec6MBubC4fDpS+Ha3G1ToIdwrymjN/q
ID81FY0mqzmzOt0T3yuwSrEusvrNd9z1etV+PI2GxDyYHP64Cioa6xJX6ZLbYBx+KhoKV2kj
Cas+p+Qw3VsyQN7utoHP6Wistu5LEzPxDbxX+EPfMyyL6N5+/UElcD7kBG/meSUJbEx6gDcz
PY5+O1SM5g3ey/TUzLdPUE38Qm/9FVtxAgKqBB/YzZk9bakz2NZ0oVdwvdtUmB/Ap3lFf+SP
UJMV1uzvYXFagZZA/KEVXK8PTuCpcCQ1v51obaa1VNBALR5akdmjQWZvKpqeusR0UW7klxmw
2yceWsL17nj49ar9eBZNedW9o9mhWMmor8iaqvdtu8jHZDA59RLj5EFcOWdQmiqeWhFOGUhd
ToVDSf1SL61ZUSJUrMwf+uZ6i7je75If1AL2OZ7gzX2OL+8AlK28wZspnyW4hnSCN1O+Rqmg
zP5C703u1R7WRmBy7wDvXWcnR6k1cG7iQi/pdbzPutjpYGGPXBLCKSRb9Dj524ju9qvsRW7n
Yz8mwwkdd/+RelTaChu2WciaZsfW70nfXDQ1SXc23lX9/Slg9tUfWlLO5fv7hZ0mFo+icQLn
1wrRkAOvsHW2LdHcGYjUzAXzEqnxA8acT2YCB0EWjbXcC0R+TkZDiapJ3P58iTKqoDspEPnN
+X63BqGAl+E3di/LI0kZbBw+sHvP/hAVJLA6cYK3rrCVluDWnzd26y/odA2XmD7BW/9C7ezv
FUiST/ACAkFybylip22FPbMUkRzFTj8AqXfDXoq6RMbY7zcDcjcVTUlOgKWJ0yGn/OCZGw8t
IXf3NbW5aHzvKjVrt0xdKija5w8tmZW4zRpdb9qPp2uTTYidq/p/CZZAWtJ5WG71vz8mo8nJ
6ZCWRv62sYJGXPHQl7Yefk5GQ4mp9hxyQRw5SrQWPfXdfLO7P0OBUAWcfDjBe2keO/EQUMj5
BG8mepZqQ+XYD/Beokf+s3TwLzzBm6mev1oE9oue4K1/Yaj2GDzFdIBXUL2BTbCdlhX2zE3E
T91oL69aRBi7oPhDK1T79DZX9DEZjTODSsVP3l5rxqneiskjehlv3h3Ak9F00apZrHVisCfE
H1qigXLbdni9aT8er42fGVRKL85DBB2PX3EN9mh++qY9jMZZW38lV/0lbtrBYvQirnc/Uf45
HY6J+XdTnRQ7Ea+wQOS3BuGvk73dGoTipKOANY4DvDmZp4lQS5sTvD2dxwUt2R7gvSyPI1EA
cvkTvJflEePCLyd4c0Kvp6boBOEBXpLQu5/HsNO4wp6YCdQwE2jaWth4KTh9W9fYrCnd64XM
RVMStUwqtVNmQfeJJb5k1G/VTz4no/FPr5nU3KrTb/hOkfKCb6Fku2/Rs9O24unahANeqf66
mYATa2XJYHQhGqSOp6LJqWVfFafgJM5bwdx+XmKuPc7oTYUTyTnJxSir7wfg6fWd0FvC8X6X
CmEDq6IHdi/Rk5x6A2t6J3hzbx6FBjestJJXHDKPaF5J0hX7lE/wZpoXpVg0mXeA9ybz3uV2
NO39Bn91Mu80rbAnRgLVOY6EM3DnUllQmreEGKkMDt+paIIVFKlslTKhvVJrqAS123b/z+lo
TFT8HpMtR88k2se2JJk3qtuelhUPo8lOV0NlgPy3MjiZt2IUo/RBMm8qmiBspVsjY21+zURH
MZbQvHu3l8/pcKwHv6sUcj7o1E889e9I9PgrFAjB6ccVY49/a6U/VF/tBG/OM1pqDGZCT/Bm
+pkTKmF1YLeucZFeUmVQT/dCb/0Nq79aSqDd+wneu8pV/GgsoMXnAV6wschAAttOTw175HMQ
A17WGvdu8mAsZIUBDqkN+rmmwgk9RZFsvUSmjNFZ4BXSS2S3nhqfs4vjJzyXXtWYKmo2/npo
SclyUE8+PTUehaOJiUrcEFSlgJ3L8dCK1BwPLjtT0VAKKW/uRs0JISgB5Q+taeu8ywJ/TkbD
vonGKJU5u3Vijb1qPOmt86cT0H+Uzh+DfaIHdi/f01cPCjrF+gZv5nuapBOq8/cG72Z8FKZm
MON7o/cyPrFU0B7ME7x7nSWB8qcHdgGlKHZvRGGnrYY9sjoIWbhi1UqWzGD3IK3RkiMtg+nM
qXAkUdNuvSuLga4ai6aA+4juza1NTjlnKf719dxAz/HXQ0sa7gZXi9NV41E4moowZbWquTI4
ihgPLaF7g4zjVDTkh1+MOpl24g4awsZDC6KRUffgVDScSswi+W6fOws4ox0PfdO9NXRvs85f
j+5X7As8sJvLyjWRgafRCd58/ktqMM17YfeyvCoxzgmO4x3grb9gq/I63jCJvwO8d41bK6mC
RPkEL8nq3bUN+dF72kPYIw+ClvzgdR7K1H2fB19bf2hBqoWq3MmjfEyGI8nYr001Iso1ozRv
iZqzjdoH5xaHQi5fW9insRGoGDzrLfuXrN6gU/V0iHgUDvuHKlaaqcXMC9g2soa0jjT+5qLJ
qdemTh+1laoM2ndEn9MKDn67EXxOhlNSJl+a2vyKVA2t+vhD3zxvEc/7XRp/RmCZ9ARvTuz1
1FXBRvADvJnwWbIC/oYneDflK0kbmh090XsTe70l2L/jjd1M+XLoCqKWnyd6SWpv0Mh/ukTY
I+3+KOUK5WJsVkAd5NdDK1J7eZBwmQpHUnFKwaxhSIJKlckSYwV6pRLvDuK5xYlLdaHcuRRl
lJHHQ0tI30/ftR/PwinJ2atGPE5gW0M7PVc0kjjpG4wnTUWTU2tSyelezdU5HyoDs0JQa2ji
MRcO+VlUfYMJSu7/dLQyPdc18E36frPIn0lFG+Hf4M0de37VA68dL+je4z9mAxg1gT7AW1fY
uKVawMLjCd76G3J5KZJgv+EJ3ktCW0/VQDWOE7yARQyngk9zCHsi2R8DvmxO8uI6X0C5skVT
wXV07E5FU1LRIA+5FBYFe47ioRUMb1RSm4pGnKvV3HOkKrl1jBLJIim50WXiNId4uDYUUnK5
ioeEztOtkWAs+ZZ9f0xG41SN/Xux7I+JLxBGv/2pJbXogXPHXDiU1K8RhVVLyVpRFee5nt1v
gvdn6PzVDGZ6TvDmCq4mBt/EA7uZ6Vmq6FjwG7uZ51liA01PTvBmnpf9VwF79E7wXp4X8zRg
Z86BXcHy9LZHj3I+7CBe/+8Jzyut19qUKUdOAuR5K9R2/OW/ralNx+PEQIpTrkLZIwL9LeKh
FX167S4z+TkdjyQOUR5tmYspOJjhD33xaPAVz4/H6+MMMkvW7j+XgrnWRaLOdGsw/DEdT47+
m+rXYSd8CvcexlMrAqJb/+fpgCiJ81b/fsQXyAgeNvkW+/t1xrdf7K8RmKw4wZtTepL8TQRz
ei/s9qRe6WCvwwn+Jnv/h+y1VBuYWD7BmyvLOXEHyd4b+7UpPd/R6SITz7w7lLK02p00SwGL
T3Vy9O4vvXp3iaOP6XiKk9ds2nslP3zhnqOyIkn5KkXenr1z8cQWGxZgpbdg4zv9hUeJvSue
H4/Xh6hwNFOKdAEbcsuS3tBIWf30fXsazyu5F+554dLWK9hF/vXJvemAKEbyjatQzH6jLh7f
2b0VXO93if51tCfkBG/O7rWUO6oNeoA3t+tFDy5YhTzBe0mfaAIVQ97QvYSPLKGJpgO7l+6J
n0AGizi9wV+e3SsXoXjm4FFqdLWVLq+DC83urSBIcmtv9jEdT3CDzsRUosSGev0ssmuz0fk7
F4/fCLVKdoYU5nOozGRacQ3/SXavXHzioY9HyHrU1s35JKy+vSS7x32UTZ6LJ2T8Gks3YSLO
4KD0ouzevZDM53RAISXjgRRjf+PgiaA0V+L70xnfl6j/Eer8sKSEsmx6ZL/+n39TuP5fgPfy
0JITK9i+cYL315kVlJ0/wVtXuUjX1GFLvhO9ObmnSSr4Jp7gvetcraWGqn4d4AVbyyvxfssP
+OI7j0wGaqphyJO19UZov3g8tCAgldvBkemAJGnPpWvv3KmDHrXx0IrGwnorzTa/QJRYpIWn
a1ZFM0Lx0AoGd68DeAX042FAIernl4VmTahJ3aoESDRKec/FE8PZ0qX4KpWQckcJ3JIbg476
G+bi4Wgj97tI9/3ABOOj/sx3BnIV7/ttYoAZnMk9wXvpX+WXJSU48PoGb05DSvJLNqoT9wbv
pn+WFJ1xu9Cb6Z+fXR075g7sZvKnPVFHpzhP9Ar6x3fNUnEYy8UunpgPOJPLzf/JmnPRil6U
46EV9G/YbTgXkCS2rs3868+VwaS2JFkyOayjfOTkAr1MzUoOGWhRtIl5ldnFvS7gFdCPhwFp
KjXnbNR6vHPYZ6SLEqy33Xkf0/GEqrPVot0sxnlh+reCnpfb9fmcjoeTZpb4NqWZgqpn8dA3
/1vD/zarA7ZIQxkoF3OA9xI/jWZw0JLsBG8nfrmDf+EJ3kv8qv8uHfVOOcBbf8PWi+/xYE/f
Cd67yt2PVS5gYvJCr6jb8qguqBeveORg0JIf784p2LlfA80y4qEVhdvaRm3/cwGpc9LaqhV6
5f6wVdIlogNkddT1P7lAlJr4xSGUPFoFPSPjoRVzJi/JnZ+8cT8eBuQ3clJ/00w1BjRgrcAV
rZSstw4g0/Hk1LuVrsy55C6gTIM/tWRwZth6OBdQSWF12MMlsAuaC5p1Cfxmfn+QXmBlsBP4
BG/O/GkyA6nBCd5MAM03A7A088bupn/+qxCsFnig9xJA6qkWsM30BO9d5VZr6gROSF7oLy/8
1otfPPI0iBouVcpmWRk8jlcVfivdHV8f0wFJEnNaEQo5YUqNzuXKisq81Vsdt/kFIj+Pc8vM
ftXJoGPa66Elhd8RAawXv3gSUEnB/Uj8eh4GKpvFom8FjKbjyWEtrkTOmbg1BnOz8dQKAngv
Fz0dEPkCleZc2ZyoC2o5mOZ6W74J4G/VDozbGOr2e4D3kj7i1BgdNH5hN/f6hSAgSJtP8NY1
jtnhVsDEwQne+hv6zTkR2pN+gvcWo63HoQX2Ih7gBXxiPGrcLj7xxA6gJuldtHZh9n8+Onmy
hB9VGRXe5uKJqWHToho5v6aoDPGSJm8bFt7m4vEtosTdWkopTcHu0thXluT7RqPG7WITz9aH
CpXcijn7MnAfWqYiOMr3zcUTQ8PqaxODW40UF4pewcclj/J9cwFR0uZUvFKjYopaH012yn7T
vT9ESRBXjH6DN9d6X9k7sNT7wm5mfdERBzatnOC9rM/JejQig7PGb/Bm1iepNbDj4ARvbkFs
zpXADfEEr2B9w3njfrGKJ34ANXGutbTcVBi98dUl3fZUb+P5mI7HCRy3bpaDK1VYrW7FOz7S
jZ6OR2KL8PUJCT4mcHpAUl2SFBuyvn6RimfrQzmUSzJZUSqorjctiWfI+ubiCdZXycyZbC/h
AbST9Y0FZuYCeulHs0rOFCNSqJrgt8LMAta3X03QCLynnODNSb649KLWvwd4e5qP4aGuA7yZ
8GU/rcH63QneS/iKJWpgf8wJ3pzms9QYFPs4wV+e5rOLUDyzCfFj1y9ulnOTBhO+RYqCozTf
XDyvNF+32jnkWAhsYViT5mu3Aiaf0/H4JiaVJTrGlAws6/pDa9r6RoTPLj7x1CyExTKr+eqA
8SxSFCQaDRDNxROKgtablFgep0lYV88WRcG5gCLNVzwm4kqVGOwj8Ie+Cd+vE77fIykYnZxg
wv0Eb07zhS8VOo5wgDd39EV7Lzg+eII3876aegO58wnenOiLZA3YiX+CNyf6KBUDZ9xO8Fcn
+uiypaCntiFapcVjXQs4QL2GJ9UyOIcn4/HXIYcXb21kXMGiRTy0IJ5ebi2Ap+ORFKLLHD4b
ogI2i8kSg+axsCBdrhQP18fZpPqFsolIh21dlggLDkzipuMJ3ifGFjxWazbshYunlrQnDvpH
JwNyCpdfWuxZpRi4QDR5EfzdvG8fq/uf//yv//ff//8/aEVb6oOjCmNzm6uhID1a0RG1gI3/
DlnF8DdNGZ1rvdB72XiuySoqrHiAt5fdG5onPsFb17kwpdpA/ZQTvPU31Oz/0gIOqZ/gvfeF
1uLlB+8LB3gFG6e7VvpgR5dvCD20cZDG3GvR5oQCPnxX2BtLG8h8T8bDidVJitNXFjFQyp6X
mN7Ra7LulhzNxVOc53Rn47Vm6hn2QVnCxstt1vJf79uPh/HkVEqtzS8XncKBBwvIn1rCXmnQ
5zEdkFhuVpv1cFAB25XzknZlX6BB3n86II7htBYNvpkJnhbi7zzsKub3O5KxTulaUkZFoU/0
9jJ8gc26DvDmdKwk6eCd/ARvJoA99YaWJw/wXgJIYXwDtoOc4K1/oZMLP2FRp/MD/OUE8PIR
oWe2DvrqGzOL8V0wxbyMAA7K8JPxhOKrX/v8H+2HVwHVL3lNH6nVwazrZDwlpt+tW3tlx+A+
xRXT76Xcppf/9b79eBhPULkiLedu2o0EC2gRAaT+8xfueUBivgGFyU/LHS0A5Ekhwr/U4Qe6
2tMBsdM/yr30kNpvqC81f49XLyKAewu05N956oxu/Sd6M/PrKUb0QOb3Bm9mfppIQJ+0E7yX
+UlNflUFJbVf2L2879WdAF5ATvBm3hcyLGCO/ASv4Em39iNxDl92HfTMDUL99O1SClUqeHv9
iilrlVFZdC4eJ9mafV8qfgzHHC8qB7yCx9qt7uXndDxO4XwLqy0mk3NWtF1xCe/jPEr8XW4d
j+LJrzYJEupZOqPuA3lJn0Sh237Sj18ISDSLv23UYioZ5bGypD/2VvXo8xfiYV/33n2ZemPU
iy6e+qZ9i2jfb8n7RZFPFZ0cOdF72V+RhHuCHuDNHQaUSgOT/yd4L/tzytk6aEN6gjfzP0ul
gK2sJ3gv/2NOguZOT/CKvN9tG1mcx5dfBz2zg9Cu5h+KVSGCNdTW8L/bNr+P6Xj8x65Nagl9
u2IFW6NYoRWF35Gs9mQ8TuV6a5qJuDUDx+b8oSV+yHmUZ77sOh7FE0wuVM+zlF6zgbJB/tQS
P2QdXThmAxKV/FoiJ7Ri6PzNCgJINnIUnw4oFBUbkfonJA3MFOTJ3olvAvgbZRV9608hFIAd
tQd4c69fTlRBAZsTvLnXr/hpCJLSE7yX2tcWexTI7A/w3lXW8EsFi3QneO9fyCX5loiWy9/g
JaXe0eTN5dRBj5w6ku/rzE2tVa5g61U8tCCeetup9PEL8TTL6me75Z4b3LvYlghp3yqdf/5C
PJVj0rpKV7/FopR8ztH2L5RvNHlz+XQ8isfJW8hnh5VK0bBUQSnfktGbMir1zgYk0VoaquBa
ixM/lPKtGLkmG10yZgNif99I/IJRW7irowF9m+gtoHy/I92nlpN18Dw7wZuZX01gA90bupn1
tcQCT3i8wXtZX+MUzeLYX3iA965w5cQNNnl5g/f+haJ+dqG3jwO8JNF3t8fHKXzZc9AzswRq
vVAp2ropSipWvBJO+u7ySB+/EE7rzQlSjL4KgcL7q0hfHWVdZuOpMQxvpXehlzAgRvpW2Awz
jfoKLm+OR/EEffMrBnXf/Jp/FShHWkP69C6gj18ISESran+1LBLYKbGq0KujQu90QKTZVyfG
0zuBDTf+1NQe/E36fqOyovaefOvHzrETvJntUSpwafcAb8/zUQP93k7w9jyf367R4vMbvD3P
FxNlcJ4vwNvzfJZBZcUT/OWM7zLooGd+Cc74qvSQhVMFm2YXUT7po06r2XiaxZRyKz07R0Ip
bF+hsGMjobvpeOLc5cxatBOq3ZVWZL5LufWX+9f79uNhPJHnk95rya1FvyKaRVohLOAM6ecv
3POAhNla1Za5diKY8i0ZUpafv3HPA2JTE20aFtAKN19+5/lWUL7flefT0kDmd4D3nrjkbyVq
r36CNzO/nkIUA2R+b/DmXJ8mWPT7jd2c6fN/Z8W2zwO7Oc/XX9wCzPO9wUuqu6OGvsugg575
JZAzPsutZv8f0ApwS6JvNp7Wm9/2cuesCsobL0r0tduBm89fiKe2GHytze+Hzv9Q1reg+u6s
b9TQd/lzPIonUnathUJky6V3uLrLXz/QMRuQOD0qHlUOYX8wFbsq0VfuAvr8lYAKsV+YsnVD
9W3/XfN8DJO+J7q8oCLvijNj2ZjJdmFBScTgpf0AbyaiLbUKUuUTvJmIWqqGGl8e4K2rXEpL
PYM3/xO89TcUq36DAFf5BG/9C1l7MvAPPLArEnZy18gW1OCyDqGHTg7+ndRqqlQFlHKkJaJ1
P9GUmYsn5GG0FYtJ3E7gjL8/tCKe1kfpoLl4SmLrmc1v1SKokGWZzAb9hYqOGg0v55BH8YSo
YBF2Vti7byxwn+ESkcRbr8WPX4hHutS3jqXfFhrMRJdYhg9HS2YDYs1K4iRUfInA1p/v0ZK/
v6YgpdzAM+1Cby78OePsaAH6AO9lfxruCmiW7wDvZX/sdKmA/PQEb2Z/lqxjB8OB3cv9qqWW
QZ36E7xgs+fRmEm5DETKQz+HYtydLJFkA5tPZo1b/6IsMxgzmYyHU2H10ziHTbCAjSC8xsl5
yP4m4wn2V5SJpWdhRQ1R5uTdnigKlss/5FE8oQ3o1xhfIWNhNJu/Q1J6OiDpVmskOf0jQge1
FklK5zxIfU8HxNEckCnMF7sQqpUz16X0Tf/+AEVBTuhY5wne3u7Fhg6eHuDNrC+mCsCq1xu7
l/O9Oh3B0u4bu/X3U7YkoIjVgd3L+FpJtYB6PCd4BeMblQLLZVJRHpqIqL2miluv4GyZP7OC
wA6lZCbDCVUY7s5gu5Efw9g3uEhKZkz45uKJ3cu3L/Z9LFxRsGzSonQf0yC9XC6Hikfx5ETW
zK8Y5oTc/4tmk5ZICWYd5JenA/JVCXZUuYT7KSwls2Su+LZ34/MXAuIsNWSkfVMwBe+1s70B
34Tvz9ES5OhtRonfgd7c8tWSoXeqE7yX+VXyDwEsmL+xe5mfxlUTzIOc4L3cTyRVUDL3wO7l
fr2mXMDG0hO8ou1wpOtWLn+K8tA/xDlY8fsRW0yxouTvyw3kJuOJafOqtVLkqAncJ/yhFdx8
TP7m4gnyx+TEohYSVOR/UbZvnF2+3CkexRM0znc8ZolJiQznkjaQv9mA5DWPq615YLmgsnuL
yN/P37jnAYUKu+8F/nmKddw/5G9p6Pxnkb/tOoI1FQLVUE7w5ua+MIgFLRtO8ObmvpD6B/0X
3ti9pL7WVHFp6zd47xorJQMHHg7s3r+v1EQNld4+wCvoXr3rKY/j97KlKM9sQ6h2X2CWRiKg
iu8qDcFbuZKPX4jHg2k19xolKoLlZJbk+ka2IdPxhKy3rw0Xbh2cuF8j6z2eLS6XK8WjeF6z
xVyaUi0FdSlYNFrMtzMZH78QjxTrOfKWPbLlWyeLb69/n78QD3ft4SHk16ZW8Cmgb7O4BWTv
t0wWd0sdVEE6sJtP2+57IHjWBnQz22upGOqyfID38r3mJBg1CjnBm/mepYbKTJzg7e0FVuGm
0jd4STvfqL3qMqIoz4xCqKq2yjEvADZXbSF8s+G0SIapk1irGZTwjYe+nPDNxqPdf6iW1emr
gtkjWrLtlVJG+eTLheJRPDFWHGMpRRrnpmCZYZF+INnPX7jnAYnkEqPsWXru+BjuivzeUExm
OiA2MT+XVFSYwX6Pb8r3t9QPbKkaWKg6wZvze2G5AAoaneDt+T0/QdHh3Td4c4ZPUwel7w7s
9vxeQ0Va3tjt+b2Cai2d4C/P710eFOWhR0itRZv5tY3+KLo3G09ruUsLcWVBy7mL8nu9j1rp
Z+NRo2KlZYriJ1xuXzO8MbAFLpcDxaN4IlXn23JWYlZfItgWeIl2II2mhWYDktK5lZgM6cYV
LueuGH8yG8hFTwfEXYz97lKd8DW8l29qhb7p3p+hHWjoSOwJ3pxfkVRBXYkDu5nz9UiL4cqB
dYky30OXkAxXdQ/w3jWuoZOLOsEc4M1vofq2DY7AvLFfnuO7TCjKQ4+QKrk6r8isFe3fTUtG
kCuNqmyz8YTJXTb/9olRVe8tSb7ZeDQsZoWd9bVuW5N8Q5OQcllQPIon0nXhDSfcWYMq7Uzy
jZv4ZgMSKY2aaHfWl2F34693hpsOiK1zlN6ZO1VwG/53VYz+EvFAQpulV9x1/sbygS31gm7h
J3pz/udlDAmmf17YzWzUEsM+EAd46yoXzqmh1dK85Jx+KB5DCgqZnOCtf6GTtuQ0BxwmPsAr
MpA0KgBe7hjlmTuGhg6vkzerBprQb5knmQuHU0wqZCm1W82KEYN4aEU6qIzSQXPxlBScrVZu
VURBa4yyZD6mlDJqMLysMR7FEzKAHkfYfZQWDO6PEQ+cDki6VvFITDIX3N5tCbeWUYvhbEAs
lWvtuVJ4P8IJyG/xwFWU7zeJB4bfAthhfoA353+CKoFOuyd4L/NTSYxaJ7yxm3kfpY4nct/g
rb+g5mhwRH10DvBe7lclRb8UKB34Bq/gfkMpt8sjozzzyHDm50ssViNNAyvJrHB6GwpHT8bD
qWgkbP0Yzp0II7Px0BLyN8oKzcXjPE6tdBLiLmAlsEzKuP0lDfnz1+3Hw3CCxSk766uce0Zd
SBcpB3K9C+jjFwKS7rycm7SWrWXY520F95Nbdv75CwGxclfWRjl3LbBy4Df3W8T9tisH9vQS
ccWUA1/g7aVnowe15wBvJ31+TwKTywd4L+2THEO4qAbPG7yX9glFjgxsgTjAm2lfTehc+4Fd
QfqGCjKXG0V56Baifrvv2moI+aLGdRvkA+fiYT9Olfw4tNKEUGK+hsQa38ntfU7HEwSusjjv
c+6nFdaLXmFcN5YPvMwoHsUT8oE1lM9zKOLADXobBGRm4xEJYWVnfE77UGGuRbXne2fBz18I
qJjfMYqES0038CT7Vg/8+6sH5hQ9wKh64Bu9l/1pSbmDhbYTvJf91TBRQRvdD/Bm9tf8cABF
g07wZvZXnbZjB92B3cv9WktvIWdIO/oNXtJ6OKi/8eVGwQ/dQqLdgLlV8nVGBWWW2DDX28Pr
YzoeTmzKOTe/ELB0LGHBS8SWySnA/WE8GY8TOQk5t/ALafBI+5L6te/wg4ETvrwoHsUTRM4f
4TAmbILmmJfRv0G9dzog8f/U7Bc8sSagktiq+eI8SDJPB8S5Rg27VgnjHbQ59Fs/cMHAyX79
QN9ecP3AAO8lfDEyrKhc9AHe3N3n/9KKTmoe4L3E/iUKiCrKHODNtJ5Sg1n9C7u5w1SS34PB
WZgDvCLdN5ow5suNgp+ZhVBtEhml2nuDZxm+fsJ4Op4QlCmdRYswOvO1ZtbE2iDdNx2PttAQ
FKpG6Nj9KkGZkYIgX14Uj+J5KQiWmmtzBltq/XMmjKcDkmJMMXTpW3mGzXS/fsJ4OiDuXK1z
Lq2YgJmB7wnjv7OGYE9FwALgCd5c5s2pZ3CzOMGbeV9LjI4QvbF7WV/LySooy3yC965xmKdw
xSeMA7z/LawgpzjBS3jf3S4f5/BlRMHPjEKoRuthztUUFfpYNmM8yrvMxtPCJc64iOYMenYt
UpaxNmi1mo5Ha8uhIZjFP0c0nhXWOWMhQb5sKB7FE1XEXLn6U82J7O4Z45+/cM8DEv98KvsK
sX+h4JT+qkRfGaWWZwNi84M9Z86sUmHnk28hwQW8b7eQYE3WwNaEE7w50cepM9rTfIC3J/qo
gfmSN3Z7mi8+ZDjNF+DtaT6tHc/zBXhzok+d8YBDlW/sl6f5LiMKfmoU0np2juTMWUCBzi1p
vtl4WjXJ2iQ3//LhNN+XG4VMxxMGFKHuoi2jZ++WNN9lRPEonpeQYK9VKedCWmG69/VpvtmA
pHR9jfJ2U4KN7jak+WYDijRfNv+Emv8PqD32neb7OwsJ+oYODiEd2M3plVdrFFjcPcCbOV9P
TUCboBO8Oc3HqVSwNHmCN6f5OAx0QWZ/gDe/hyVZx47gA7ukm28wUcmXGwU/NQuRHk7A3V9E
0IJ5WZJvxPpm42n+ugaxIIqh5D8nyTcbT0i3EFsmEQIllxYl+YZCgnx5UTyKJ9J1TEVi5NUa
2Dq+Jcc3G4+IB9LKS4pTwBduh1nIdEBsQsr+vrFvC/9wf7jyFTqCYHloRWHo0RwCmAdasFMu
IMi/Sduwp0Jg++OF3ktNcku5gvKLJ3gzRbZUDe5/fIO3rjMrpWzgJMAbu/UX1BycF9QxOsFb
/0LuMQMOul2c4AUby0tW55ayXA4e/MRPIWYjlEMLMBsJ6mI4qWjxROBwMh5OUWPNfi/J2jqo
18VLRGGcwN7l3T5/YX1UpDdnlYWVGypwuGQgyWyUiL/8Ox7Fk19N85V6L0XFFGZgSyZ4+mjC
ajYg6RbSiVS638s6GtAagcM84sjTK9R8N2DfuPzijHo45skJ+z+dI/+TBA41dUWTeyd6c1Vc
Ih0G0r8DvJf+qTwYGj/Ae+lfy0nR6ZITvJcAEidjtDvjAG/9CyX7Catg0+AJXkGYaNQIeZl5
8BNrhfKyVqg9h+EKfLVaMyE8FDmcjMe5XKl+GDutVSdk2FvkDy2pUw4r47Pr49yctXF+SR1i
9zZ/aGr89C/0YpQjvaw8HsXjRKH66lDXnD0emC8tkW0kGwgsTQfkkVizGEcP0Sg067tCYalk
GV05plfIiuRWe1VTgdPY/55J0n+CyiFHpxNIqy70ZuYXUzcFZX5v8Gbmpyl3cPztBO9lfr2m
go5QnuC9zE9DrwRsJT/Bm5mfRL0bZX5v8IqeyD5ifpd3Bj/zzhDLTSpTowpbZ6zIW/jFZ6A2
PBkOR38sN+5F2b8vlPitKCaT1YHu3PTyRJU/q3EMJIBCKouIH7U7nvSv1+3Hw3hCEoWbSFEp
vXewA2ZWSOUvLZEj4jcbkIhJr9KcoUsH5Vn9qQW585KHV43pFSr9ZetYNfTh4czf1N3pm/j9
MUqHUlKpqCLKid7L/4oTpoyash3gzR0GTosNNYk4wFvXWYhSYZBDn+C9/K9yHHqxyv8LAAD/
/+x9S64kO7LcikSQ/ucGanDOKgRoKgnQ/gdyz4yIBl4jWR5MHlbdfomuvt0Di1vpSWbQ6B+z
BP87wHv5H0IUxJP87wAv4X8j7bnLPgPv2WcwtygqV7DKNZtZWuJtN1S6nownlK4litlmWimr
R7lG6dpkpDw3uz5iMeFjzE4uktJE8dCSzN/ovnG5Z9yKJ4hC9Otx5El7s7SS3gp/k8qjG8ds
QL7bfGE8HrWQPdxKAEfedvMrRGrQkZr5VSqZbP74m/xDtQ59cySP2gO8udevlqZJxZYTvLnX
z9+22fz4Cd66yv7a8x9n9it8YPeuMXPpmCTNJ3jvJ8RHXik7lPUELyAU+FLhIg7gyzoD71mb
EHYJZ1n/jApZTZUVxfVG9qqX7OuNeLSHk7HIY3okd1rFQysyfi8J7Pcb8Qg+8rHcW6Ws12hZ
oUXW+svK6L/226+b8QQxqNRQnVPEBSNd6l3Cj14aDn69EVA4tEBVaA0kP9W9ZB6m9dEVY3qF
ul8vfM8R+S0jWQSok90fH8L3N2gdapHkxj2wm1mflJ51DTrBm1mfFupZS5MDvJf1NSlqyYLR
E7t3jYUitZEUvjnAez8h+V/askPaB3gFS3pZF/VTmC7LDLpnaULS1T9gq9adWWRZ34q66JD1
TccTrmKMVEMYMlu1WMT6XhoOfr8Rj3BkjzQ6azRrNuov5iV13kFamS7DjFvxRKuexUS3R9Wx
JzuNZ+cH/o0k/X7D3Q+I2GmVVgPRZkknpkVpvocdxW923ERATYC7NkJ/IUCa9U1dvT+s748q
HWqBrLftCd5M+FpByJ1KB3Z7kg+ylisneHOSTwo/NIWTlDnAm9N8Uiol1/iJ3Z7k6y2bhjzA
C+gE1IGfLF2GGXTPMIMYakVT8mVO6rS1JYfVb+jebDzauzlRcQ4LlkzEtmJrHOxe0fHvN+IR
IjAhQGBoabr340k+uuwybsUT6bqQhEQVxgZ5SZUV7AhfTlx/vRFQsKLO4LvZ40neo3ck+eZX
qBs2k15rN05bTH+SfCvo3p9SOhRNdqmf4L0nbosJ+OTl/QRv5n1W/O9M9vMd4L28D6ovXNqG
7QnenOjzC0XLurQe4M2JPo2acjLdfICXJPoG0hp0WWbQPcsMshbl3Q7s7/ss8VsymDwkfrPh
aKeGVZ22ZIVcVqX5ZFDcnQ5HhCR4n8RMUJbHLknz4csk0r9226+b8UTCDrpWgOYbTvFnZUL+
K0162Q779UZAxE38X92czkqyHXZZlm9E+6bjab2imsTPM5tY/k/N8uFPaB0m82pL7m7LZkx2
qwq2Xixb7LvQm8moFpWs89oB3kxGe0nmz57QrWuMFCpySemQE7z1+6Pui4bZsd0DvPUT+olT
KDlxd2CX0NBX504Qg8vKg+4YK0CB3sAqSifGpI4jLBFBHgvKTMYT2jANmRFrF0uK/qwSlIFR
9W92faiBhMGt01FMzxWveKcA4KCrlS4jj1vxxIAIi4hpdAQ0zubr1igKymCsZDog8iMQGXy3
+T+TuhyLFAUfGhu/2XETK8RIXP2tINY0Ta0/YyXLON8fUhTspbYkSb7Qmyt/VBqljZWf4L3U
7yESmG1zOsCb6Z9z9iQ7PbBbv0F/8RTLZiFP8F7yp5B3rTnBS+jfYMqTLk8PumOxEB+OGlW/
xDVf7WRm1R9aEA+/VEP7mo4HCzjXrtX8PK6958qb/tCKenrXEf2bXR8KJUHVRq3qVvo3FpSm
y9LjVjxB/3r0tzbp3TR539hC/2YDIlMRQhR20pRUsFwmKD0wVp5fIWn+E+qtMjf/If2o4uOH
/v0FeoLiP6+snMwTvJn1heotJuuSB3gz6+M4R5PU+QDvZX3KpfbkiMQJ3sv7qBZIdpYe2M2s
j/zvTCpGnuAVrK+9GmKIU/iyqaB7NhXU2I8tqs0qZD0sJ2tNd7RkJuPBQuq/+SZhUJft0sM1
xfRx0m9+fXxdDFRjoZKtuGuSfk1/v99+3YzH2UF13udL09HIMN11uER0eTRaPB0QRcLcujkH
a9n2jUVdh/BSbOD7rRXyayrHjJYf8kn5otkV+rC+v0dMsBbGbNLvRO9v+upJo7sTvJf+Sajv
Jb/DJ3Yv+bN4XyWl7k/wZvLn1wpIavOc4L30z3rR5MzJgV1ALvClTWwcxpdFBd20EOHOlSzm
YyHbkLrGc+0xAPzyLJ6LBwua+Wks3SQt9o2T/gf/lfwNO8Fm14eaYhX21wRqz1bkV5BzJzOj
DoPLoOJWPEESRCSSZNVIksI/q5SkeUT+ZgMiqtj9IURuWSPsVSMnL7W+v99ZobhmVieWSl0k
XZOfWqEP+fujQoJUFJId9Cd4c3tfSCxkpxAO8Ob2PigCyVHNJ3brGvuNN2Zys6I8T/DeNeZW
uiS9x0/w3k8I4idqtsn0AK8gfC+dD+IAvqwp6I5RQAsBCe5+UPnlIxtTW5Ptk/YqV/H1RjzO
JcS/Kj+ABdKzGUtaMM1GuZfZeNiUxZe+NqNkv5U/tKKC2HQ0034ZU9yKJ6q1zAitqnWoSamD
VUKCbVTjnQ2IsPpliTvVJlnXgHhqCSUfTbVPr5ApOHmt0BggbYL38YxbQfj+nJBg1qX1AG8+
cc2ZkmZP3Cd4M+/TeLNltWWe4M3Mz8KwPZkyOMCbmV8v9LArSDG/J3hztwE+hH3T6jIB/nHm
d3lS0B2HgGB+2MWsVek9WVxva7rH5OUU69cb8ahU6ojawmM3q8aywlsoRFMG5/BsPGzsL1qk
8MBL6rwuYn51KF55OVLciic4HLFf2HyFEDSdR1pC/IaZvtl4KJpju9+fRLQmy2RbxGWmF6j7
VaMTRO4f8+KInzLv+8Rvt5YgR6ExqSpzgDdn+qAoZKc5DvD2TJ+/zW6ICe4d5Q2Fxa6W5XtP
8PZMn1nSuOYEb8/0cc8y0gP843zvsqSgm5YhrZtKQ+cUaXfrHZm+2XhUqyKSH4a1J50Gt2T6
ZuPhDuZ/fHnQkg4bWzJ9lyHFrXgemb4Gj70WEolbxQRf9l1+vREPYaUqlYGqYV577+cTfdML
ZNrUOmtvzvvStfdPom8B3/szYoJQGifTFyd4c4KFinCyT+cEb6Z95lwzqZBygvcSv1ZLpbQG
zhO8d5XDM5mzzjAHePM+lNIgneh7gpcQv0GDPV+uFHzTNaQBsvmxxdXq35Pom45HWcIxBJxf
YPKKuCjRNyR+0/GwqUJ3EtalJWcqdyT6+PKkuBXPI9Gnfs3gLuhM6Wc1Qu5k+qYDohi5aR1j
ahzz8ns/numbXyG/CfrJGXMdcmMu+T8y0/cjeoItaZbjuAWvpWWDJrsVBaGVqsm67oXenAIK
Hc2sw9kB3sxIe2k92Wl8greuM3KYvSSbsU7w1u+QupWedNg4sFs/H7IUq5Ic0T7AK/goDFzF
+LLN4DsmBvDgB8YmatKTRqWwhB400lcyOV/T8WBB8vPUQoOFkqYZuES0pD0sLV6Sg+nl8d1d
Y2Ja/LaQzH0vGZlxOjoQFeTLM+NWPJGHpKoSCi8xkbFXVNAGM03TAZGZrw4iq6gmPeEXqcrg
aKjpjRXqTrH9tSCPVORHVHA37ftDooJanm/kHPt7ojfngXpBTM6enuC97I+pJGtFgdzL+0gL
S/ImdIK3fntcofTs6O4J3sv8hONKkWR+B3gFU3opwBdH8WWcwXd8DKIJIhrAwMlfFcvlUWCN
AN9QT3oyntAG7AogzUAlKcCHawQSO74q2X6/sT4oBhRNYCI9meeCNT4gtQ6m2fnyzbgVTwgK
GqqEdklFysvVraB+j9mW32y4+wGRdbHGENPlQukWvZ/NFX+/s0LsLBa4hsEJpv2LP4KCq6jf
bkHB8IzA7Jzhid5eg7asTfAJ3s75VLLDjQd4L/MTKmDJQe0TvJf5UTixJhX5T/Bm5qfRoZP9
Dp/gH8/5XU4VfM+pAhn1MSHZrOV1ZVYwv6Go4GQ86Edq93iAtTJn2XnhFVbGhgNfh/n1CZ+c
Ts4t/P+kk34rmB++bA791377dTOeWqAjAJOvT+UO2ancFdY1Yyvj6YAeVsZAUVkPJ8WdNehH
9+ZvdtzMCrH64vsPyDTblvIRFfzHiwpCLyE1kSSAB3ovAWQo4LsyOZfwBO8lgCEU2JN9Gyd4
LwHUkCq74YMR4M0EUIphdur9AO8lgGqhV5lMnx7gJU2IIwJ4eVXwPa8KrGbdyRgb9mQmBpbo
vI2FBSfjCY3ACtGBGFK/yW2+RldQR6LS88tDXUgqKycFi9ew86fAyG8226+b0TwEi3tMT7NB
zc5vrZKUfinL+fVGQERkRlAB0TddWmRmSSLzpe7j91srZIgohk0Yk0KWH1XBf6SqoBSWtKrg
E7yX78X4cNZV7ARvbvGDyD9lW/ye4K2rHAPE3JNjMSd4M6tvBSW7ygd4c6spl5rsTzqwS9je
aOTk8qjgO44BD22ZZkRKVClrd71o5OSlCO7XG/GoQGvQukQSJjs7vWbkpI9GTmbjYVVzHtF9
k0N2dHrFJfc3LX6XQcWtcKJii6LhuKGh9J02qFhT5x1l+2YDIjCOhkV1BitpT5QVs8bt4QT1
mw03sULmt3wU5/s92mWzKzS15T58728QFbQC2ebUE7y5zltLz7pmPrGbSZ/6FTt72BzgzaSP
Stdkm9ATu5ny9WI9qWB6gjfvwVaSlmRP6ArCRwMfB758KfiOS0CLoYEq5oSvoib7ZduafNhQ
XGY6Hg3pxq41XEOSegSLCF9/2an4/UY8LOZMAphQmbPiiLyks49GF4zLleJWPMHdzEOpwDX8
av6eEePZePyWpCZWTWMsKk34lgypDMu70wvUoUuYhgA6I0/L/3zEZd4nfLvFBKVYVs3jBG9O
8GG+1HeCtyf4Ws+aBB/gzVwPw6gzyfUe2O3pPf9vlus9wdvTe60nuzZP8AI+QcPz97Kl4Ju2
IeA8xUlftCVlJUuWpCfGdG82HBXprFVimiMr3bBGS3CoHT0dDxsqijPyKLGl6d6aBN/vt9uv
m/EE3RMCfy2r/wfS9GiRa8gowTcbkEfTEPxX9BhOTrfz/XyCb3qFYsdZa2Cd1NIr9EnwLeB7
f0ZMsBXR5JjECd6cXNFSkzePA7uZ9FkJufW0lGCAN5M+KVFWSbK+J3jvGkst2Ra5A7t5D4YF
bbIs/sT+eIrv8qPge34U2KvWx+ih/5Sz+sSLUnwjGcHZeJRJwQxBsSV10uOhH0/xzcYTGr6E
6LcGoWRWflGK77UqyL/226+b8TxVQbqgsDqHTTYQbcnxzQbkVK/rQ/aIpSbf+6ua+Gh0y5he
IWev6HTSXwnN8m2W/5E5PvjHywjeGkBIjh4seFkuYMh/RtywcTHOflMnei87qXpDKvoAb+bI
vQglu/ZO8OZ1dtpmWf5wgLd+h9we451Jt58DvPUTYtcClizUn+AVPPnlpGbwlsvHg+/YKkjp
1XooGWntkvS98IdW9D7yyPdiMh4sBNhR1YkyZ3+JuMY3Rl/OUnxPxwNhCm/YGbEhZtPx/tAK
FoYjnnzZeNyKp5Xa1K8ynZlJkhKh/tCC9YFmIznNuXhq4Uqoxh2wOrPMtgqumK13mvzqhfD9
RkDRG2MY+qB+hn5sVrbzvj+kbijFFzxZ0j3Rm+viVGo2OfXE7iV/TIWzts8nePMqMxS27Fv3
RO+lf9gKJV87B3br5yNqBWuSWJzgBeQCYKA4J5eXh9xxVpBirQl3P0cUsrqS8dBPk7/JeJzH
OfcTiJnwxpidc16RsmoPD+dXZ/FkPOB37CiNi6pKNmPlDy3Yb2PyJ5eTx614gscxtFYrC0FS
zcofWuFJ91B3+M1+uxuP07im4js5ulSfOzpH/law2deugd9vBOTLYqAtxngMk2r3s4X+D/v7
8wKHTuQw2+V1oTfTPgtRnay38hO8mfixv6OSzPQEbyZ+XUuV3M/5BO+lfQqlZsX0T/Bm4mcl
K/l6YJe0Qw68leXyzJA7DgbROyINKnfSzknHM39ohVoPv6QVX9PxYBHr3Jz69UZ52rdih/+G
9s3F4wyu+78YKBSIKLnl4qEltG8gcCOXY8ateKp/NGJfGfHtDNWyrGJJQM1eKY9/vREQiVDr
/pKsDy+dLE1a0r3w0v36+42AUJj9jy8T+G8onfWbCujD+/4aeUPkEoNcSfp3oPfSP4hJ3ORL
/QRv7i5ozjmzHPoA713n1rBEf33uI57ovQSwS4Gsh/EJ3vsJqxXhpBboCf7psq9c3hlyx8ng
UfatrMJxNCff96vKvkMKOBdPsLlONVzGACXZ7olFlyhcv8zMfr8Rj19vKmCjVhsk0+H+0JrM
34gCXs4Zt+IJPYqGKqE9i6rpkZi+okzabJRqng2IDLQyteiNlKSvdzy1YoVgRAGnA4quyPCf
EfVrYbrf86Nx+DYF3K5xGGps2QnoB3Zzn18tzZIdYCd4c58fFIVss+QB3rrG/jsuLS3G/MDu
XWPuhSWvdePYvZ/P7zoKyXzkCV5B9mxUdrvsMuSeXYYgIwh2FcuK2Ycq54J4xAbzz5PxtGIt
RDqY9eEvkSwjLplV6i8tmb/fiMdvCkIC1nqHZD62renxw/Yqnn/tt18346klpp85pntEn3rm
KSqxYsONBa2nAyJCIaz+G2KAtD/LksaC3l9NqH+/E1AF66Ya1sw1vUL0sTNZQPb+jMChn6Et
96o8sJs5n5bKyVLHE7uZ8Wkhzib5DvBexmdQGlCS8h3gvWusLQw0c2v8xG7mpP53Zh2+T/CC
N/yja/zlGXxZZMg9iwzujWoIkHRoyctePLSE841KbnPxOH3zI6thb9qj1z7L+ZacwDqq8c7G
ozVq1SDNaUVSVLMtSVhClVGC77LIuBVPsDeDSq2ziHAyA1sXkVgYDHZMB0ROjKozWEKzZIks
HlqxQC8H1L/ficfZqy9Sg25da7bE+2ntW0D59kscMiVb6J/YzVzv0RWf5HoP7PbsHmpa6eYJ
3rrCBH79h2Q99wTvXWOLmbDknPEJ3sz2uEjyNXhgF3AJeNkvFmfv5Y8hd+wKoHRnEczI2gGS
I4jx0Aqu93IE8Ws6nuYfrRN1hla5WpYb9RX6hn1kHzYdT7RZVoLK2CV5v3DuuqT2WUdjQ5c9
xq14atFmFqoz1Riynt/+1IqxB7/8/3bD3Q+I1GrkYOOCwWm/jyXF3NftHd/vBOQvA6va2Exb
0uhqNmH5IXt/h76hZa3dT/De87bFDyZb8jvAm3nfw5Q2r3AY4L28T3sJ16gc7zvAW79DbFIk
y/tO8N592LVw9kJ/glcwP3qVFYuT+DLKkDu+BVj8POTaxVmF/6BzTCkeWtHG10dZvrl4IinN
flcJ71iUtLXvilpF6zqqs83F46S0K7JYfzplJOOpS7J8OGJ+l0/GrXhqsVbVd3IH65w1U6pL
Jsbhcd/9zYa7H5DfmmqYJPbQomzZrNgKz1dnfqMJ3umAKlgId6lUM/pZPZq/nfnhT6gcJinM
kvaZZfMl29UE1S/xyWLkhd7MR7WoJPM/T+xmNtqLZLu1TvDmVQYqrWYX+Qne+h1S70Ux2ad5
gvfyZaFCLSkadIJXsFEY5SEvHw+546ogxXmb/0GRsG5Ly8kssY15qVH9NR0PFqcE1Zz/BzlM
3rpwiU9v622ggDwZDxQKkWp1RurLlO1zWOLi4ff50e3ncvG4FU9zoiwVSU1AW7J5KAQIl5Ro
R22Gc/HUQr12vyiy362e/D2XtVvRtNH7KPE9G1CUJExChl96/rqAU+/gv52M/ncSE7RSs3pi
F3ov+0Mq0JJn1Aney/9CIZCSjjUnePM6YyuW1OM+wVu/Q65cgLJmjwd4L/9TJ509qch4glfw
v5ev+ziPL08PueOwIEVioNjpn2FHymXv/KEVujJj/jcXDxaQUJSprQFm6wL+0JI6tI7431w8
TuVYfYOLPixXsnNAS1raxvzvcvS4FU/wvzAMRCfo1CCtJb0kuzrkf3PxBJNrvjwdelOqnLZV
XqGTgy8vhN9vBIRhAhYdyERMycmmj6zMP1hOsD8kMbNygk/0ZuLnb7SW9jh7gjcTPy6Ynd09
wZuJn7GfJckm/AO8l/gRhaRV0kTkAO8lfgal96xBxQFeQCxQBoa3cplUyE0TkWiR95d9+BEn
dX39oRV5C4ZXROlrOh4MU4duzpNAuybbwXCJp0PTl+or39PxBIfjrv42a2TUs2X1JXJ1ddjw
enlU3IqnFjPw/yCHgCXVtKDgEvGVkdnedEDkW42ClzM680vP464oQ8Mw1TwbkB9K1Lv1cFtM
V6HxIyazivj9IT3BXnp2LuFC7+V/ZKW2nix+HOC9/E/ChzZb+D3Am/lf5xJjmFk96Sd6LwNk
yotyn+C9xenqtNOS5fMTvKT0O2gM08upQu85iWio4TpnIlHJdsj4Q0sY4EDebTKecBIBs65O
x6C2HGPCJaXSpqPU32Q84OSUuaNJQ2VMj4MvKZWOGKBeRhW34gkuh+Y3IgEwheQ1ahUDfEmY
vt4IiChSmdLCUaTlFsgfWjE+TSMnkel4MEbbiZz+NY8pzQA/48bvT6DslhPUEGdI5loO8OZW
v1DLSpZST/DmZj8oku6XPMBbV9mPjRKK98lC5RO8d5UZS82+Ok/w3k8YtomWbTo4wEtyfgOB
Gb1MKvSeSYVAN+Uq4X6aHfQusoIhyaj4NhlPK871lLRH0i8r/BgPLYjHXookfr8RD1v3JRIP
q2f7nNsSASC/0g9EBfWyqLgVT/WtY8BQWZF9kbaKCr72Wvt6IyDCSipViZQ4rzCzoh2z1sGw
03RAaKw9pDnJ/zeZHfhYB/+TRQUtKvxZ5vcEbz5xrYhiMtt3gDczPy1Us21+B3gv87OnLWSy
UvkE711liSaYLAc5wPvbTdPD7wd4RVscv2IWcRJf3hR6xykgTKGraoVeq/9JTlCVFfV1Z34D
OenJeJzEiTbtFYSVelqK7+eZ32w8zvyQQ9kX6nbmN5AW1MuZ4lY8weGEDSzEk6il1ZeXSAsO
q73TAT2qvaLQGD20dLJvBZVtozmP6YCwm/+LfY2YmqWzsR856QXMb7e2IBdL7tgDuznVB0WT
DSEHdnuiD7Lihyd4M92T0igpGXWCNyf6tGi2i+mJ3Uz2Ql4pOXV8glek+WxUaLu8KfSed4g2
soeEdKeeTaH7QyvIno3SfHPxhHcIkD0Sl5Q2bVwiYNL6yLZrOh7BmE8xDKO4JDdqS9KwvnN/
v99+3YwnaFsPtTvkmAlMJ5FWDEU5NxrdLmYDIqp+tagNsWpSomkR16svzcO/34gH++Oa1MnX
Pyvn/+F6/2RpwVoU09KCT/D27IrW9EzHE7yZ9pn/pdmJ6AO8dZWpSkFMViFO8N5VVoh20eQq
H+DNvaVaGLLK5gd4AbFoL9/zcRBfBhV6z0BEEbi1igwsSZO1eGhFRx+9qk59TcfjHA7ZSRL2
jqLJDrhVBiIv6+/fb8QjQhzh+O2Bs9Nii3iSjLLKlz/FrXicwpkaq/o1BqolA/Kn1gy/DqQF
pwMigVp9jVQwLc65yEGERg4i8wE5QQ75xxB/pLTFy1wLy9/O/H5EWtDvccnRiRXFlGXDJrtl
R0BLS3qin+DNVee4JWW7rA/wZj7aQwwsm4Z8gnevMvjCZTM0J3rrt8i1FpCkAM4J3voJka10
zEqXHOAFr5ahvKBeNhp6x9QglAIrNgb/4xwhd1NZJi84Ighz8YRSoCo237YoCNkZE1xhQ2Nx
er/kB3PxQKHa+mPc09INejCZGLojL6OXicateGrpncNXp1dE0KzO6Rp9Gd8Rv91w9wMiU/8F
NehVNNuzu0pfZshIZwMKPUu/oHb2y50kVbTq5E/ob2ek/430BZHCcy1LDQ705pRkD/HL5Evw
AO+lgOxfS0uKpj6xuwlgL5WyIjNP8Gb6R4UtKzJzgPfSP3HmnixEH9gV5G+kLaiXk4be8TWQ
ImJgxKD+TWpaW3BFk95QW3Aynoe2oJ/BtRsZJZ1OFmkLqo3SkXPxQNxhjYQbKGGSK8Fk7/8t
8nf5aNyKJ8ifLwzHALhvOssmu1ZoGv2G/M0G5OTPmqJWVrHke3WHuPR0QH5kNuxMEA4u6abD
j7j0KvK3W1wQW9GscsuF3sz6Qo0vSUxP8HbWp5rkpSd4M+8zLD1riXGh9zK/aMzMFt1O8F7m
p/6XWvLHcoJX9CCO5AX18q3QOzYCGjq/NYTR/C1vyRKJLsnDjOUFJ+MJpUAkCJMuIOu5QsYi
ecFx4m8unsjhMTZhIIUG2YEg+nlxmcu24lY8IRNTfctB2BsDJY1FFonLjHsQZwMiqoBdiImb
U9qt8oIwGnGaDQgr+Du1VxP/DSX7quKpD/dbxP3+jL4ghTlmckLvAO8lgOx/JyVnZU/wXgIo
rVTJDqAc4M0EsLfSNfsRT/ReAsgtNHWTPbEHeC8BNCkISbJ0gpdUfkfqgpdxhd4zFlHtZg1R
YnIyd3yFes4SAjiS/piLBwvFaazChFqz5i+TjVS3kn9z8UQezySGf5t0TZroLqr8jgng5Vtx
Kx6nctpbNxAOb5Hk63yZvvRo6mk2IHIG2Frk0FtLthos43+j3N9sPNha9dtGrdD8F5RdoI++
9IIhlN3qglzQkoNtJ3gv52tQpGeTfgd4c7ef/6WUzZwe4K2rjEqlc/Ied4L3M3vJavcd4M1d
p1wgK8fyxC5J+I1mTy6/Cr3nVyFgXLl2CCO0LJ9YpC04yr/MxfNQmKmRIGtSIdkwsEph5mU+
6fuNeFhNfYlUTCXp7tCWKAABtlGC+XKruBVPKMxUxhpmtVwBsoIsG7QFZwMijyZkHyuLX+DT
nX4rfkG9v+qV/X4jIDTSMMfjZs8kdo7wTW25D+H7G7QFtVB2huIEby72xo0vmQM6wZt5n/ov
IGvTcYD38j6rpVp2PuEAb+Z9vTidy2Z0n+DN+9CP1vQnPMAr2uJ40HZll0+F3fSpcGbBZoCc
rVMtkxYcnMOT4TiHCxVmpUZNpCZ7WcsKS0wnzoO8y3Q8rNFqK+CEtiflLOOhFXmxkbSgXS4V
t+J5SAt2xt4bNuiQpRU/Ly04HRBRAxNsERElU7E75GamA8JO0VXCCAY1mcP4iEr/I6UF1d/k
SS5wgjdn+rD4ay950h7g7Zk+yOvMPMHbGZ+0ZA7kBG9mfOQX4ezozgHenOlT5wjZfXiAlzC+
QW3XLp8Ku+kjosKPXh70H3Uyv1qWxCP6qnb4NR2Psze/REHv0LVqstTW1jjh2ZDyzcYjNb6o
2hCaZt8s/tCPU77LpeJWPEH5NAS/uQXlT+bLl1G+0R1jNiBCrMAeEyJAfrBjjY/IoJ10OiA0
FSR24ieIyUH/D+X7JysMhkN5ch79BG/OsWiJybZkjuUJ3sz8rCika7xP8F7m16nUrBfLCd67
ysLFt1eSgxzgzfuwl5r11z3BS5jfq/d8nMSXT4Xd8xER6o8iVQ/dh2yyb8VB3MQGE5aT8QTz
Y0WLEZWmSXa+ivnZQFp6Oh7xX6B19mCgJYui/tCKsQ6nM7/db79uxhMi0dzQGqnfNHp6pHfF
DPnYM3g6ICLfa5UMoWdf/Ws8g1vvAwO5+Xj8DljNyK9Pikml13+qtPQ+Wvf//uf/+V//93//
j1bripG4G6dV7hW4e/4hOfmw4EeygJD/CYFFBSl+5U/OWR7gzQkwKJA1TjrBe7cZ11Kzlfcn
dusaA5ozqew3eIC3foNCVJ4+pZlhjwO89xM2DNHi3CKf4BVknAbyy3b5iNg9HxHutTrhE1CE
rCzUEtM43/6DlsvJeHw7dKihDtLDAy83MhgPreBGI1O/6XicF+ljihdb1urSH1pi6oeDFl+7
bERuxVMLggk7d2USwbQ6Ni4xrnnZufL1RkC+Ps3flMaRVU7aSPpTa1bo1XXp+52AiFvF+CcR
YpaN20dccRXr+xO5WEU/pzg5fHuC95I/atGvney7PMCbyR/5jyfppXKC99I/4kLZ/rondi+1
ghg8T85UneCtn1CxlmxH34FdQC3aS2W4OIovJxG75yTCxiGiUat2p6lbqd9LavE1HY+znhgn
JQXVDkmRpnhoQTyqozzsbDzaIqGMSPZU0kvFs+Kq4VfnEfW7fERuxRMkjrg3CGM8Z+jp+u6S
gvVLpvT1RkAhfBlOPGIdkh6Zs0QprX35/UY8vss8JAilVdZ02/JcdvHD/P68smK1IEnJbNWJ
3kz60PdXMl31xG6mfFxatub3xO4lfNzKU5wv1dT4BO+lfMZFstbiJ3gv5YMYT0lehE/wkuL7
qA3uMuuwO9YJUaf1Wwe27jekatk2xRX2Ne2RHHl5Bs/FQ4WaddMmgLVxLh5aI6nT66u22O83
4hGOJkWsUXpPznHQGnu/h3z3b/bbr5vx1AJVnZSzYUWrkNVUhCXdBDpqu5wNyNfHfz4abcs1
O6haV81CjSZtpgPqathjsh8Y03rac52+H9b312gqAoVmTrK950TvJX8cFdy8qCLsnrqRVkCz
+b4DvJf+CZZGyXr0Cd5L/7QVv0Ini6kHeG83C1J0OuR6Wp7YJeRvYKZil1mH3bFOcB6HTQjF
9yGbJfVU1+jr8Es5uK/peOK7hq4qlZ0tYZYsLenxUR6onUzG49dDP4Nb80VCZ+m59YmHVpC/
l42K/9pvv27GEzTO3ydUnc1qheRtYxH5qzrqLpgNiP3uxBrD1tK7ZWujvCTlJ6PrxmxAYg0i
+69M2XaJOjmF9+F+f1JPkbVQdo7+BO9le42LZmV1nti9bC8EEpMNUg/oXj4vvUC2W+MEb/3+
kLBkiwoHdu/ng1pUkp/viV1R2W2jyu5lzGF3bBJaaSYVaiUkrlkr7bLC6LGJjXIuc/GEZLQp
dgjblKyr9RqjkaY0arGajQdIuzYnEZCeGAozoRUsQkdJvsuW41Y8YbCBUh+10Gjqy/K8OVuO
fxsZGvG82YAkdJv8YqHRGCvpYfEVtXd8OQP1/UZA7AQvDJMBfd+17ArNSXB8iN5foKMoMceX
na0+wHv5HpKfoVm/+AO8mfE5Dc7aAJzgvaxPpUCyqHJgN3M+50nZE/sE7/2ESqVpcpjjBC/g
FSgjFcXLj8Pu2CMEhWMCMFFomJxnbwWWGOYNZRTn4oGwe4BuypGyTDaBTJo9/Nssx6i/ajYc
RnNCKUxdKNkv5g+t0OhrOkrvXW4ct+IJXw1UJ+Tcuy9QthK6Yn1CaOm32+1+PM5htTJ36AiY
lwhaERC+VFr4ficgEeDOYaMpyffB7OD7h/T9SQ1Fca6evHcd2M25PS01KYp2YDczvf8PAAD/
/+xdbXLstq7cEQufJLEB/7D3v58HzEiTquSJB6Jp2rnxTd0kP1o500ON1ASBbt9eU1Itn+Dt
9T3QrM/PAd5e38sGpRzYzfU9zNcfn9gvr++9cjj6vRwO7L2KMreqnJ7cWFPfo5GDzhyfKNVV
JIRaYxg5eQSwKBdPRoYms3yoYq9WoVHP86EVTXzXsbt/3W9vN/lEpc4X3kVX979j3plvTX1v
kIs3TagigzWLgjJhcrZmldK7TMr8+AQhbTFSg9qg+6XZg9y5rsRfqfcDvBMrl9jrJyXfE7y5
vhfBItnTmgO8WfX10jlpNXKCN9f3/A+lbCTyAd6s+h5dZVnZ9wTv/YTm0geTc+MneEmFb/Am
tlcQh90L4iBA37zFeIBk+48WVfgqXSml92k+LnpMhVkaheVErpBNS4QFGg8qLtN8oreyN4WG
qlkv+SUdlq4r/ny/vd3kE9W6xnHHEbRuSbPOMHlZQeiyBvv+CUIVQsP6rwce+42dyg9HJ7vz
hEz8adDFatT5sie7c+1JP135cVr53XIkS3qRLXgoLRsq2W0d2Py1mew0OsF71aj/oZLO8T3A
e9Vo2AH2bLjWAd66yhEiFy0kSUX/BG/9Dv2tW4CSEzkneOsnFF846clfygleUocc9H3ZKyPE
7mWEaAwRA3NrpMl5BVxyoInaBweAk3weLSaILqQEqbXcXSRrYvva5XD0xzSfsENApYZhf9KT
dUie9PO4pUZfCSG3+IQa7WBdAKSDpscvlqjRa8eV908Qsu4/HrLIijTLarcVTUYx6/vHG+4+
n4qm6irU/AWVzSuY7Zv86WL0P+Ud+IgdTVoHOnZzJVIjRzzbafgEb9Z+Ukyy0xsHeLP264Uf
TV5J4+gAb/0Oaye/s5I+7yd46ydUbEU5mYRzgldUInGQ32evlBC7lxKi3Bmldq18IxJ4ifYb
GclM8pEi0HrnWjla9HKFLlkzY9J5YBw9yYcLS5SKRRVZkoW7uGiBtPA/9I/329tNPqHipAnE
dografbIdon2Ax40t04TMgZFcHVO4R+ZrUTailrxYwLkD3fcfULN+URR1W83p5RVs23qJ/Qr
/r7fPhDDIDhp1vtC71V+EpuLtH/gE7xZ+Wk8qbOe0U/wXuUnLjdbtovpAO+t+mktrkWSwTUH
eK/yAyzJUaxArqj3XVqFxTv4FUZhN8NCWvh4NLM4c0res5NDhH8/fZZB3+EkHym9ETTrkHYg
iktWnD0P379zbLgQA1PUx6xzslM4LlpR7YNBbp+9gihu8YFHr4N0dLlXa0v7K69odvAN7Ejx
zRKq5Ey4IWi4MKXPnpdIWPrzHXefkCBFah9aBck2usLkpulX8f0Y60CsxV8AaeH3RG8Wfq00
yp1IHdi9si/cADXZefjE7hV96jIk3cB0gPeKPpZSOydF3wHeK/pqKyTJp+IJXlHu49FR7yuM
wm6GhVR02cyKANlZ3LhohfQbZehO8pGiqqakjXr0zSfF3xI+/ZLPxzQfLvqICukaLq2c4+MX
LenTG/lG2yuL4hafkHHV1LVs69Rd1O60Dhw3Hs4SquDKjyMsrhkmm2hmbZb/Lv4uh/M/PkHI
n1ZISujSTxpmR07kd+Tk8yMnu70DbwQDn+DN3X0RB56c3z3BewVfWAJiNhn4AO+V9a5AKmcN
wQ/w1u+QtRW07KzJAd57HyoVTAbqHNglvX2j891XEIXdCwrBphECGqd52Z1UDCavEHx94BU9
yYdKnIWCGWKDnjdfWTJp0gcTn9Pr02qr2glRs2dtfs0Kq2iiK+vrv263t5t0HiPGAhU1/JUp
eai0aMSY8YrQ+ycIVSHiyt0eA7npEeMlB/DD3r5ZQnGs232NKPaB6RFj+c0FXqD3vmvEmLJF
qhO8Wfb1wskS0IHdLPpayfpIHdi9kq/5Gy49cnKAN0u+XjDbGHmC996DnQto8oV1gr9c9L0C
KOxeQAhGklp9NCRhsscKlwRQYOWR6JvjQ0X8VQXctIX0S+Ze+0Urqnx9EBAyvT5GvixMbL1V
ya7Pio0kAYya+l7xE7f4hH5zmSS9O6XohdtpIYiXhN4/Qchv4956zEX59indpbhE9eGlJ+LH
JwgpkKqxL5OB9CyhuX3Tr+r7Tg/BKJgkzVAO7GaxF+GlyWf4E7u9wkeUFXsP7Ob6npZeazYh
5AneLPZqaS2ZQHmCt9f3zJKToSd4STff1QFOvHxfKRR2MyXEF9ilhIBxT2YcrBJ7l+LofZpP
FOu6Eol/W65ic3z8ojV20aOCy+z6tNZdSTwGUvLT1StOXvyuGB3pvjIobvGBEll91KL5kRsk
4weXlfhG5kWzhKo8zj75WbtMJ+d+fYlvlpDfZ0i11i7sO8CcFvgt8f27XQRNkq4oJ3jvG5cf
JzfZudMneLPu66W2ZBD4Cd5c5pPSKTl3eoK3n+w2SrpZnuC996E9ehyTyu8Af3mZ7xVEYTdz
Qpp2A9d+Jr1tPtsdze7O8Yl8uAomWFkk6QqyKB7OLucEPj6xPFY5hpGBqEJydDcuWnK2O6ry
vWIobvGJeh2EE42Rb9qQ0iaCX1/lmyXkNxoThpwVpbzwWzK6O2wmmCWk/kQgI982CUO6bDnX
PvrThd+XmAgiJZv9acVTdtmAyX4bwSZJsXeC98oAbHGmlE0pfoI3y1Fz/ZbNKX5gt64xMRSq
yeHRE7z1G2xCpTdN3oUHeOsnFNCS9eI5sAseKmMbmVdUht2LMlGunSNBLGZX0yPFK/jUPqoJ
zfGRYtoxAt6YSZJGlLJEu/kbfHT+N8eHSoOqSGC+rba0ofWcp8ctC8FXUMYtPqEqq/8kejVr
DMnn5DIbmZEWnSOEBWKE/UkKs0X8FW3Hz9awP9xv99dH1ff2wFWa/4DShuNzg1k/XYn+pxwE
QZIprCd48+mzFcwm2D2xe2WfSqmWzJI/wZuFnxVRzQq/J3iv8CMu0pIn5Cd4r/BTKDGTkXaP
DvCSKuT1eSDCmZUR/3ZL+kkzoMYVDbNdsv5+WMBH7PpNPMvHf1KtOpn6iP+QrIPgil8hNr52
j57lQ8VQuFlFIl+obIqdLanatet+h5PP200+IeJq1dbR/G+crkIuKdoNzKPn+ZirWGEVtObX
ZkdmbMF+f5DK9/EJQhUVqPfu6985OSv56x797zUQJCkxdZ4sjB7o7cfPIMna7QneLvxa1r7s
BO8VfsK+686OXB7gvcLPwmEnKZ5P8F7h51+LJGfuDuyKil+/rsD4K+0lK26GhjTs3HsjVUo6
leBkUuk/Kn7XTjKzfLS4Oo6mEyVC41xBKS76ctk3x4dKrxEtqFC5WrIKHhct6dK7kkl/3W9v
N/lAQeuRT2PMVbIN5ItsBOGyb/f9E4ScBht3tW5KSbcBv2rBxokArq3K5wlxJQZstSPV5Ls2
LvqVfYtk3ze5CGpJWwg6dK/uk3jlpI2jn+C9uu/hCph1a3lg96o+5dKzwvmJ3av5mka7c07y
PbF7FV8P28zkBzzBK0p9A+NoBHppipthIS0cl6D7m6sm+6VWab7LcI33aT5SnEq31ir7/5NL
VPoSyTfIiZulwwXQmmDYIRomzRB5zSHiyDzw5PN2k0+It4gJ8S/LBQslw1wWmQc+5kD+cL/d
J1R9K0ahxw1Ie5bQkkhaS9xx9wkJuDauBA0QIGnhEVf9ar5PT5rsNg/0d2dyeu3Abu7oi61R
Uug9sZv7+agkX5iB3Kvhay1Qs27AB3jrt8fV9/89+UZ7YjfXl135QnKo/Yld0sl3NTwYL11+
iYh74SBYRWsMLYhAsg4WF63QeDbSeHN8qLgc6siRA86abArwi1asj9F1J9/8+lS26K1iiGnV
7FTJkmHV0TjxyeftJp8YJ3YJ7rrVhQRysjVn0TjxuK43S6hKtGsotOqiq6fjQZbU9XQk8mYJ
CYGRb5Aserjz8SC/57kLRN73jBNHPqFlHQOf4M1tfFQwHQh3gDfrvVa4pseJn+C9qq/5awGS
veAneLPqa66UksXHE7z3PvSdDnCy4fUEf7nyk5eyuJcNEsqPEJvrMMge6C4SfqO+qjk6VMQ0
qntKHTXZUr/IKbpfOl9/fGJ5GkOtXbm11rOpTX7Rkj6+kfCTl6y4FzzBoK6Qoatwl/T555Jx
Ypbr8fV5QlXVfzpMKihqaeG34sh95CMzT0hUagVVjpnv5ET+r4/Mv9I0sJakk9MTurm2588x
S7bLn+Dt1T20pNPSCd5e41PNhr0e4O01Pu7J8JcTvLnKJ6Ulz9UO7JKT3FETvb7ExN1YEAyz
3gitp+Qc/CrTQLvqOX+f5hMFu6i5uHC1ZC/iqhpfu/aHnl+dqgi+7uL76pq0U8I1FaRxjU9f
QuJe5gSZ67wGcVr4o0p8s3yqtDC/ZAtDnORDdVWJj66tiuYJCaE2fx5Ys9rSK/Rb4luh9L7P
MTCfCeLYzQW+6j+yZGDECd4s+cIC8IZb4ObiHhdq2XGSA7xZ7tWYHM3VMU7w3nuwYkS9J4vM
B/jLi3v1JSluRoJUV/Tmbw9/YVm6urdG8F3xeZ/mQ0Wcj4skA1ZJPshoMrX075IPRse6s+vT
NEqVEr7KLftcKSu8KYeRICeft5t8Qr01qmDqd7Pz2moWyDLq3ZslVMWs+v9cJDGkc9OWaD65
tHP8+AShGD9BoqZq1pPnQHHV/6Lmo68wC8zmXW0WLtka0IJH5QJ9/F0GhpIti5zg7QfgtSUz
dE/w3ttMoSBlmwoP8NZV5t5KTdrvHdit32AVLapJv+8TvPcThsl4dpdxghc8VkRHA83tpcBu
5o50l3YgbL6ftPR58QrfF70cx3yf5iOuwKIlX6Pmxsk0HllSdMNOo9PIWT7iYrJVV1/SLGlD
IEvO8+lRs/zD/fZ2kw+UyOGt4JvvSLvJyq8VResI6fvj/XafT+8RcKPcQWvSAtQvWmFjAzyq
ic7yMWqtdutae08PH9nU+vx0efwfcjAUf88nny4neK/yk0cnUFL5HeDNyi/sc7PjoQd46yq7
XC9JE5ZA7tVUxMV60nL4BG/9hB1raZBUfSd4xUG4jEaa+0tV3MscaYQCDaM4mo0gL0t6OJVH
LjZzdKQAVRcV4j98EU3e42XJNFKrI9E3x0cLNVcTjVsURZP1lLhoiei79kk/+bzd5AOPCXrf
TEpD7pbcZcCSEXpXSaOmx1lCXSzmxHzPRNaT3lt+1YqyKA5l3xwhDB+oJhKVXieWDlWaqlv/
yr7vNy9EK5gdgjjAm/UeF9RkE9AJ3qz3/ImbdTM+wZv1npWGuUPPA7tX8xkWzQ5gn+Ctn7A1
KNlwxAP75YrPXpLiZhRGbabA/vZgS7q++EVrTsJHzWhzfOTRpd86SuuamzmQyRb9v5+DD6dc
ZtlY+IlwAzHFZJ/CouAVsz/fbW83+UBh9cedVejA8PjGcufgS3o5L+233z9ByJ89FDsmqX7j
SbZVcImCFRo1284SipbUpv5y970GpQ3F51IAfxXfj/EtpF60Z88nT/Re6adUONk6c2A3dxJg
oaQry4HdK/tqK5Tszj6we2Vf941j1iD/BO8t9VWLkNRkqe8AL3gV02Wpwl/F+ArCwHtBGN0i
LaeKK6Vsix0VW3EgOjzgneQjfr8yx4u4oXJ2d1NWbA6xj17Ek3y0+N0N4tIPkDQ7jegXrSiN
4aChAF85GLf4xIAakCn13tA4WdGPq1aUxi7d/t4/QUhd8EEXguhVheyA84qoH+LLwPGPTxBq
0Dr7zRZH14BZQnOxiL/S71vtC2u4g+R+gyd4r9hDdYWZPDU9wXvlXhgTZrNdn9itaxzV2fQR
xAne+g2ySNHklPiB3fz5tDzzdFMf8AleUecb5dLhKwADbwaUCFX0969v7RWzBzlrIokv+9/e
p/lQEXRVxAhi2CXbn7hEjvfLoeCPz/AJtVdbdFm15BZjDR//cweVPnzFX9zi48LNFLqxQZPK
LSsm5ryQ/17pu7R/ef8EoYoui9gfQs16dg5uNsft74Tkz3fcDCEz31s6pWZS0wY9v1POC+Te
t0w5ay++4rk79wTvVX1hE5I14TvBm1VfK8m3zRO6V/NxKy2bl3yCN2sqKkTJ3f8J3voJfUtf
wugrV0A6wAtUBV8Gz8db+JWBgfciSipSIxcspJDO1SlLjHrqZTvS+zSfKOqDdagNBSVreFpW
jBTiw+ro8h08y6e10EfVXCGJZq16Vpy+E1yq8r/ut7ebfMIDRQWYyTUfNM2e78qKMQ7SQfz1
NKEIivYNk/9DtCWtTWHJL4ho1NA3Tagx9MrdbzjfaCSD62HSOPNX9X2ri2H3ZUv6BZ/gzUW+
6s+ybDPfAd5e5KMGeSfDAG8v81XNWgMd4P1lvposaZzgzZ+wFtTs7PMB/vJC3ysRA+8lYqiw
gREhQNo5ZVGdb/QCnqMTJS7s3TWfyyOuW+t8hgNnm3k+zBB+yBxJe2mnniVzrkPF94rDuMUn
6nwcXgXSnVC2sAxrzqnpcvD9/ROEKtYYcTWq1i058rCqzjfyrf4EIVMygapCHbKa/LfOt0Lx
fY+boRYTSdb5DvDmOl8rYtmAsAd2s+zrxXq2XnKA98o+4cKclX0HeLOo4iJZN9gTvLnS5zuK
ntzTn+AFukIuCxXxHn7lYeC9PIzqC1x7q0zSkhP7ONm2/fd2PhxV+ub4UORhAHRBIIJkmwUt
Mcz7Q6Vvlk9j4E4u+pA4++hbk1fClx7Jf91vbzf5RKXPTE0V4gwhbQiyptJ3OZry/glCFWIS
qkqovmppF+sVlT6Eq+Hqj08QathbU4NIr0w70Mw94X667OOvMDRMTsstyateNl6y3zpQe3JQ
8ondK0Tjz8R0ct4TvFeKPrwAs9bVB3jrGrNGfSJbPTvAW7/DhlL643w1cxse4L1StHOBbD7i
CV4hRWXg6oGvvA68lz7C0pTgUUXhZPskLZnxRO0jZTDH55FcI9Fp4togPVO8wosaDUdKdI4O
F3KFq4hWhdOGn0sGZVyJjnY+r7SOW3xcU3bhrl1bV+rJjO64aolwG1gHThOyTjGURb75qdDT
XnsrCNEoMnmaUK1s1AG5o+/pvjYK8KdL0f+WeWBNHnGc4M1lSC3pLqIndrP2k2KcNEM9wXu1
X+tFkoc+B3brN1hdKnVONmuf4K2fUNUKSnJ7foKXFCGvZlbjVfyK7cCbMSRCQo1NqWpNDzGs
ULI6HPGc4yN+v3J9yIpINsv6B8qKImS/XJ+PaT5cXE7EsHetRDUpLHhRiauPZopfoR23+IBv
xxW632oNWSw9k7HCb2vgsvz+CULG0KFiZ3RS7Wttlv9BaFSEnCXkeydnpMzcjJK7DZjcPf1K
v+83EASJaLLkWOyJ3qv6xJ8AlixKnuDNuk9L0nnpCd2r+Sy+kty74wHdW+vTXjB7fHOC9yq+
cCGHXK//gV2i90YeMq8QCrwZEuL/3e5apVn8ldR7umS8REYznnN8pPSOQGIo1VrSDCsuWqH3
RjF6k3y4SG/iL3YGg2xlzC9a4iEjo1LfK4TiFh8oHKZ35HecKz5NtmXDkvkfwsscyvdPEKpk
EgE7rXXKDu7Nuu39w+VntMOYJSRijyz1p0t5OkZvqvj/q/d+jH0gctHsjv+F3iz7WmnZZ8YJ
3iv7ajinZ4dNDvDWdRag4q+S7GzsE7xX/nEvkEx6OLB7C5JYi4Ll1vgEL5AX2EflvlccBd5L
CxHTKPa1EH9JizpakkGGKqPW/zk+Epl3oETRD61JJ09Zk3n3GC29fBnP8eHSqYbJhzirZAdJ
VMBXaAv48+32dpOO6zjGGC22cNyjZGMBLNkeu0T78/12n1CF7isPpJp9Zi1qOGQbNRbM0vEX
JqChxrxWdpodJreDv9rvW/0DfdebbZs7wZsb+8JkPTnBcYL3qr2HJ2DWcfsAb13lqM6mrcie
2K3fIGsrEY2QbDx8gvfehVVLdnbhAV2gJJhGB22vHAq8kwqARfz7A+7WVDk7VLzkXLdexmq8
T9MJDarWuAmTdcgOYyypW9qlEP/4xPL0sD81Jm3pcCS/aMHtRq5f/ni7vd3k45qtGrBrIpd7
LWsJ71ct8cVpo5a+WUJVBPkxYOJbJc5KoxWjA/5yG7X0zRKS1pr0ZuILVZMmI7NNl79a7weY
B1YsgD2ZOXmAN0u+HkODWcn3BG+WfC32sFnJ9wTvlXxRmZWkJ/MJ3i76IkYgLfoCvPc+tF5q
w6RuPsArSnyjhFZ6pVDQnUyAEHEPpxJXFS3548c1eWpDN5lJOmEMo34NV23OZ6f7CtoosmGa
D1CLSRvDrpT8UdCSgONxSAi9Iihu8XmEhNSHjPXlEd4aEgL1Spm/f4JQ5dp9efzHg/73bP/b
EuHHNCjyTRNSJm4sav7ot+TbNq76FX6fFn67/QOb75PTISFP8GbFh6VmD9NO8PYiH2U35E/s
9hKfJJv5Dux2tSeQni1+greX+GrNzjoc4K8u89ErhILuhYQItxrudADQ0iEha+p8NpJ7c3yi
ZOcC24URUNdkoNWyOt8gsmF6fXoNtxXuTRRqMmqy9BVhzWaj3cUrguIWn6jz1SbQDdR/vOkj
0CV1Ph6Nik8TqoLQ4iypklB6dPfr63zThKRVJYPWoblAzq7Qb51vhdz7njqfFLSkKdoJ3vvG
Zd+RJ0ejDuxmzRdW2kkvjxO8ucrXCqXnMw/wdt2XbpM7wXs/IbSCPTmbfYIXvIdp1FdPrxgK
uhcTItUf770bqaZTQmTFaXW9rIq9T9Pxnzyw60lp+PSzyBX5VrQlGg9Od6fpQFVmV31syaZE
v2SN5ht08dErgOIWmyjWqW8uXH4Zk6QDKJYYRiOMNhmzhCq7jEVwJSvELd3Ht6QIO2obnSak
IlJZGVVcl2dF7Nxh2k/XfF/iHIjJA3NcEcjx7/UO7MV/VUn/mAO8V4liJLylI3af4M1a1KI3
KKtFn+Ctq8zhq5NMWzuwW7/BJlo0GwJ8grd+QqFaTJPmFyd4SQVyECdBr3gMuhePQS4P/M1j
QqjJPZRftKbT8Kpi9z7NR0qEYqgScuTGJq3Gl1i54SNd5FIbzK5Pj4av3knNZVzWlrsvaAjw
rfxIjb7CMW7xgcfOh5urHNdwWZtVWLL3IeCRGp0jhAXItwnkTyJfpWxSqV+0YoHaaPMzu0Aa
JqINlABMkr26s64TP12M/oe8A7mwYtLF4wBv7zY0ydbQDvBe7adSGiYPiZ7Yvcqvxp4xOe58
gvdqP6JiyYyVA7tX+XUqnA30PsELlIWMoorpFZBBNwM/GASlNU7/8GnJbKdve0bv4Tk6Ump0
GJohql+Ze23FRQv49MtG0I9pPlwQO2DFRtCz8d1lRV8rAY5Onl/hGLfouIKzSKgmMzIEyw5k
LLHGGZpGTxOycGHyNXLR1zXtsWwrCDGOTp5nCdXwFQCoFsPeyXbqX9Pof7VzoCRzhE7w9nNn
wOye9wBvV3ydkgOxJ3iv5mtatCW/wxO8V/MZlJ6uOh/gvaqvWkFOvoNP8AJZgXrVMBXv4VcY
Bd3LChHS7h+yo4BqOt53heyrwwawOT5aEFz1tThIt5qclPaLlsTWXTpgf0zz4QIMhNhcV7R0
hveaARO6jF/+6357u8kHCruORe2goJgd0oIluYL0eDL/4Ya7T6iq/8XNqnTIdjvMyqR/eDyO
Cn7TK9RNwW+65rqckj6ps/0Bv7rvxzgIEsSLKusgeKD3CkCJCZKsIcoB3isAKxbmpHg5wXsF
oD2yy5JFvwO8VwC2VtSSk3oneOsnVKLieinZonuAVxz4XiYexAv5FUlBNyNDuJKxRiaZWVoA
Ljnw5YGn2ySfsLqy8CZmMKw1mxa34kk2Toub5MOFXJj7/aMsSMlfBS85kCe4rJP9db+93eQT
ZtAU9t4KMQGSLDQvspAeTxjPEnLxxzEGrhTOe1utZWBY+JslJNTFdxsGDxfBr02W/hWA32oj
WEvLNn+d4M0dfrFVSg7wnuDNHX7kf6gkA1cO8F5pb1agJztRntit3yCHWVF2kOOJ3b7tSPeO
neAlp7yj+ssrkYLu5AP4jiPmMrQThZdvdoJ1yWxGvZxgfZ/mQ0UZ/KlkAo1qy05nzLlh/P2Y
93I64+MT6xNzM75GvjitJt+9EVGzQr5eHsP/db+93eTjwk1bdJD5Rg2rSrqatKQ8Vkf1vllC
VbpYxSiQ1ey7M6qEKwjpFaGPTxASFpd5KL03sGRI+6/c+zc7CVLBpFfVgd3c2ffoQk+e8x7g
zZqv+YY0+QlP8NY1JmilJlMAD+xmzadFena++ADvvQurfyuadEA7wSuKfDjq7XsFUdCdZIAQ
cPHK6tYAMGkigWtydOulSnqf5kN+O0BrVs1IW1LF0qQpxj98ZQY5cdPr031VEEMphUtx1ldm
ydAADfyj6ZVEcYvPwz9aGJhjaCA7pL/KV+byUPT9E4SqRvNl95uOKiX7JJapvlFZeZaQ+PbC
94Cdw18mOafy6yvzr7QRfKRs5X6DJ3hzkc93sMkC1YHdXuKjbEvaCd4s96Bgdg76id0s92KO
LCmmTvDmIh+VXiFb5HuCv1zuveIo6GZaCLiUiPnDHs7Re+XeyE9mjk/U63wj2tmkgUD2jHqF
uTyaXZ1Rf3xifVqoV3U1zi3v99OW2CIOi3yvMIpbfKLI12v8BcBi6TCKNUW+UVzINKEqFSVO
qB9jr1uLfFxHG4xZQsKKMTUu1Thb94fJNo9fufczbASzkuXAbi7y1Rgwyo7vPsGbVV8vNTt9
eoI3qz4rLfsJT/D2Mh9lu7xP8N77sElhyTYYHOCv1n38SqPgm2EhMUrJvtS+TbJc79sy3Tcw
b5nkQ+HXpEKNI+Eqfbi7xBexjY7apteniwJhZ0D/t2wZdol5i6uYP95vbzf5RMEOXe7FJG/D
7A5+VUzc6HB3mlCV5rdct8ro2jynzJfpvis7p49PEJJe/T/cAPym47SQnRuz/um6j/71VoK3
RhGSQwgLHpYLVPL3GBzW4pui5KTBAd5+FM5pg8MDvFklW+nZg9wTvLf9EbqUxpYss5zord9i
ra0YJr14T/DedQag0inb53qiV7RB1kHQCr+CPPhOrEIrUWZB3210FU6adbRFNoc2Ei5zfCIY
qIII+53LnJzukkVK+ZLPxzQf3+4bCJJqFZKWW5+4aIWwvLQQ/+t+e7vJxzdZFmnXrRH5/5NP
yzVuN3A5NfY+zQf8ARRR5KTmOjntIb6iLdr5DCry0+vDHcx3mvIYTc82YMxNRv50mfwfMjnU
0nrWWvgAbz6VxNI0+Tw/wXt1gUqxbLPmCd6r/6hB8QdV8iOe6M36T0tPtmgc2K2fzzhEcbJa
f4IXaAu6zIuId/ErzoPvxCv0gtalgX+HKEnvxl5oxYSFwmDgeZKOFLJWu2mUeTCZHC6FV/Bp
9Wp5Pqb51AIckeECvn9I+jbWNYY3yIN5Z36Fedyi449kquzbNRNzpZwe6FkSTjJUfnN8XMSB
WFdi6f5DTxs32oL7jaANjsanF8if+Nxb7KgrJVvm46Jf6bdG+m23OaSCPevRd6I3qz4umHxU
HNjNmk/9pZOt+R3gzavMFsb1WTejA731W2zoG4qWtVg/wHtVX+9FsiMwJ3iF6rscsYj38Cs4
g+/kGLRiHbthM5dKloxWbmuCQIb+1pN8pFToVn0zUJtCco38oiVGh30wkDDJpxYOAz0jfxtr
TTao1UUthKNBe37lZtzigy5JEX3pq2DMCidlxRIdy320zZjjE4keyiYKGNq8po/Gl+g+Hh2N
zxLqRITNbzv2f9OskJ0buvoVfj/G5xCxhCNSUhkc6L36T8kfbNmetAO8ubkAi2JWRB/gvess
rphqT7bwvNCbFWC0ZCYPH5/YzWe+5I99zh5XnegV3ZGX3YTxRn4laPCdQINeWtXovAOwyGpI
Fv7aikSQ8ZnvHJ/HmW+EnLicVdas0+GSM98+cjqc5ONiDnvtWEWp9qSxSl1kDNgHESf8CtC4
xQdjys5QmutaVzDZM19cMgM9VIBzfEIBCkcfbrTwVM4mnMwlwf1DAQ6MDqcJdaEaxlGqFbK1
2bjqVwF+VgF+g9Fhp6S59Qneq/miwAPJJrUTvLnTj1wiJW3wTvDWVRZuxXVm7js8wVu/Q5Ze
rCcndk7w1k8oTYv/mcnv8AAvUBSooy6/V3gG3wzPqBweJMoRnJa0Tl6Rd4P1smLxPk0nXLe1
aatMLvssxydmaFYIvmHT1ezyMEuThq4pSDT3+uUlkYOuJ0aC75WccYsPlNbFutWny1JygeKq
FYrvck79/ROEqt9pLBD/iHS7bM1vzQqNFN8soa6irvga+TawYZbQ3ATWr+L7CV6H4YWf3Hyd
4L3CL7qlJDsIfYA3C79W9JE9kXQ7DPDeVUYo0JLi+QTvFX4KxTT5HZ7gvcJP44Q5e5B4gFcI
v8sXV7yJX6EZfC80w4USdwrd14Vzc6m8pjRWaWA/N8mHCrfeoQpVF7NZZ9TJ9vR/jHeM3sOz
6wO+NzQwVxecXh742mmIv263t5t0ortNK7qmjDl1Sx8l2pJQOxmkKE4TqsRgzsd1OQKlQ+3W
zHcM0rOnCXUwNMGGfsNZssvPr5paoV/h9612h7WwJJvTTvDmUl/1HUVyyOgEby/1+Y8/b3gY
4L2lPtGSPPEK5F6tV6WkD3xO8F6tZ1iSLUlP6AqdN2zqe6Vl8J3sAi7IZBbVMDNsWSGBS9KL
bfTeneNDRbVbB7LwOUxX+FY8HbDjqMI3uz6RH6bqoqizQe4Hy0sqln+o8L2yMm7xCRnhG1yJ
jnClms7K6Cua4FgGzprThKpKdannu03gltZFa3ythxW+6RXqZKhNekwR5Vfod5J3gdD7LqND
saTF/AneXOFr8RxMFvge2M1qzwqkG1QO8N41llaoZtf4AO/VfA/XmGRD5AnerPmkYM8dsh3Y
BaqC2iBdgl9pGXwnu4CLC74YDlUUrcmqb1y0oho2nOCd4+MCrkeSKzfkanl76xXVvfG57uz6
MFZtER5bUZJpM7ymkQ9HkcX8ysq4xQeK+V3WfHVIGmdzv/2qFZ18WAehidOEakeVHsMPJpLs
hY+rvlz1zRLqTZ2IVRKF2tKdfP+Tqo+/wuYwOfCzItX632snaC4uk3W9E7xXiVIr1bKDJQd4
rxZVKJCe2z3AW1e5t0eEc9I35ABv/Q4bQbQxZG0tn+C9n7BqwZzOeUJXKNE6UqKvIA++E6ug
paO/dpDDqY6SHfE6ear0dy+Zy3rq+zQf35ZY71UMY0g6O1GyorqFZqOJktnlAevQgB+nzckw
Zb/dloysDidKXiket/hgQVc42shfHK51sv7hK6yLBsL6fZqPS+Tugrpaj4EsS45k+VVLGgEu
h74/PrFAECnKKugbhfRbrMBve+Eqwfc9NoLRmf3/1s/+DwAA///tXWFvHLkN/S/pZ6uUREpU
getHA/UWLYr+AvfiXANcnCL2AXf/vuTuaHx3ycgcrSwb7fpLYvvNerialZ4o8r1vrGcLeHIG
klwsxqL+Cp7M+7Sw0ZqDXMBTR7kguRSM3qwVPPU9lL28y9kqIr2Ap94h5+TYqh1RwSPOnqnB
/XA188A91grJea8agplkQY7GehO9aMTZs29wv8548GixjUiAIUMxJoqHSBT7vDk+h+545AOY
kjYqx1AwJtvxCw3JEjd06p6et+ud8QiPK17oRcqMHowOxHrRiKNnaCQhO+MRGodMWXYaoE7R
yWoeU4YcPW+y88MZA+SLfHCydv7kBFalxz52fiF/ry8kGMBZW4gqeC7rQ/mbYGV9C3gy6xOq
SWAXElTwZNanRcDGupgKnpxLQ2ecPE/QyYyvCBE2am9X8JBsX8PEAVdTCtxnSgGUgDEJKzUf
MqVB/cTY6CfujAddkWmJE3jhRyFaGd+Ipv5nGF9fPMr4QvAow5MxG8/R9aKXrjbE1ZRiVzwy
IWdQp2giEGph9CmAIYpF7X7i7oCSamFHH6NaEZuPaYf0E3vYmhEO54yQ9mNFGZ2QSzI2z+lV
F843iPO9joZgDI6jMRe0oieTv+xyNM4ZFTyX/CXZ/FhrqCt47jjLttRZFeFP2LnUD9UIzqjI
U8FT77BwcWrmYFSQPoFHJPyw4RuCqzEF7jOmwMDMBZEjeTP9G6HN3laQ7oxH9gIxM2hPZMZk
7PGUi0YkZPOmee/hjPHxEUn2D1HGyHrYkYY0AzWK2p6et+ud8ajQHBQqAMfDazALFA8YoBBa
3U3dAcm2KSU+au5pbaiV/o1ok252FfePEAQU/ochqZWQ7ZHrbQe60L9XFRDMMl0alXAreHJt
HzhiY49EBc8lfKoJWIxmxhU8dZRVcS8no2Z0BU99DyMVx8kbBQQX8Nw7zMnFDMY7XMAjKBK1
Mn6rKQXu8QjQUg1UaUIhz1SMXld60QiK1Cq46o6HgmdS4y7NYpo7TUaMD2OL8vXGIxSWhIwz
+5CMBYthCIUNx8Xgmeftemc8miDTPgahxyjDlM26K0M4bH7+gesICClGlduLarY9tb/4aFb+
zBPXEVBGNQoOwSc0zsPQWVVwYXxvQUAQHGYjaangycSPXbQaXVTwZOKXXYxsFxBU8Fzix1lN
6qztuyfwZOLHqtVgFRA8gafeIQbUNLfRgHYBDyAWMbWKrVYvCtxjDSAcIXCKTCkk2c1ZBfdG
rMM+N4uteuPBiEe7K09IwWgtOSZ3mVsNn93xMMeYMnvhfmT0Cgmd/Z5fdeQ2WoxxtaLYFY8w
hOLB5+yLLwWMRgV61Qgm67eY7M05AUUJRJPlFFIy6g7AGGrezvX1BpS1pd1DEiorzNws7t11
JHRhfq+qICirZzZ271TwZMrnnZEKnKDT83wBjJnICp5L90hd/Yx9CBU8l+4leVusJwoVPPcO
WU/kjRujCh6R52suv6sTBe501khF7XQJinqBWunRGEWZVmVfbzyEKlcCIao2ojXNN8QoJG2d
VB/OCCcJ0ZOlN0Qib2yzDmPkSrzfGp6nx+16Zzya5mPMJZBHVl2ZqWm+zaP3m3MCQo6IICth
zGD0NxqU5vOpYQ7cH5AKTOlZtXC+aPSm6VXIubC9tyAjmBxb2/gqeC7pizpFG+vlKngy8WPZ
JRmP/ip4LvErxUEyZiIreDLxy85YR3yCzs3xYdKZ0TbCFTyAVYSWOxyuJhS4z1RDbk5tARKV
DGwVWx5CYjO0FuHeeITEJoxqfFLQSCpGkdiWSUhnPNEBhAKeZGwgstklZIjayaa/8dPzdr0z
Hu2vQ2Hk6koTIZvd1PIQOZom6+sNSFgfMEatkQgZJ4tHt3J83SPEDMEXDAC+GHus5aquLOxb
Z30vIiPorWbyQ2zkh7WZzBYSZMdWk5oKnstFfXYYjHX9FTyZixbHeYeotYLnjnIJzhuzpAt2
6juoDSOy9zXe4AKeeodJNjne2LiwYEecN1OLG6xGGbjHtoBcYEK1w2VZ2Ixch4aIe/hjJ/Mm
NeiLB5364ArXSSV7MHYo4RBhN+GiDWG37nhkEpOZljxR8cayL7loiB8atzKQq03Grni86qbm
TBhSxIBWJcFBDnytXqbueAIVkrGPBFa5AbnoxY2KO+MBJ8MTomwYYikpGsVkVAb7f5GJ/h8p
CXrdJFqVBE/gySfPxa4tXMFziZ+KA7Kx/a+Cp44yU3CA3qiJsoDnUj/ZU8jW2b4BUfDcO6Ts
IGfjJ2UBj0hExlaXyeqXgXvcC8gRYM5Amiwt1iMIuWjEaXqzsbgvHtRpKQbhFrLry2jVlRmR
5/KZW4txbzxcZOCLCi9TNpJzvWgAuTjK8jzzvF3vjMc7nxATMBXInIwKZm7EHNSWke6MRwWh
yUfdaJTI0Vi+4cdkipsy0t0DBBFTTkTq923W+e5jsxfy9/pKgt67QsaJf0VPP3wGo2XDgp3P
+oqxv6yC57K+hE6WEaP28QKey6kKOq3gMWYkT+C5d+jZpWT8oFTwCNbX7PVczSlwnzkFcY6y
vZeFiwNbvUNoSIoMWqyvNx4fijBYkKWY2aiNRWO8mMtmy8yhOx5VugnJ+0zInIyL8Bh5HGFJ
Lda3elPsikf1Z2OSfUYKqrhszPnpVQMCanoXdwckBMmXCJ5lbxftx88jeGxsCkj3BkQlFHXm
K/oJMi4V0DklXHjfm1ET9NGVZD4YX9Bz6R96h8VoFFnBcwmgCgRma4/xAp46zsUXWSKN9ZsV
PJdesUwmYFsYFuzU+2NVLQJjl3YFj6B/m6vXX1QcptIL2mlPUQqAD7J+ZWtMNCZJlqhRDNYZ
j7ZzFwLvoyxisVjp0ojPYNs7rnt8gDNFjAQUi1Hmn0adkDbEpGl1p9gVz7F/1WvbSfAIVi2j
3v7VrzqMt7LmN2cEJPy8qOqeMtpgrDof1GEcNvVFD+cElFWaKaaI8shlszzipefk/J6T2WqC
5NDYE79gJ5f36cNoLNup4MnlfSrRYXVYXMBTxzgGlQc05qoqeOp7GIUFW7POC3bu/QX5m2wk
zBU8osDPt+je6k1Be5wCgotAuiCoyRob6YRcNMQtrjQEZbrjoUjCJki4BLOx4ErbkkdkLzfp
+OGMeAKhihIf6/yMtRl60Qh2FBoCRrQ6U+yKR7NCnlUMO4dSkreSiRHp5RA3hfduzghIm/NV
ZpnUhCdPbTEOmyWyh3NGKAvbA5kRQkJ7iV/fFHehe29BSlDzYsaNSgVPru4LzmdrW8cCnsz7
ssNj/sIoJajgubyPZNlOxraJCp7M+9CRMZe7YOfeXyaXyfgUVvCIWrjUSrusphS0xyJAhpeL
1vJEL/zPKI4oF4055W2l+Xrjwaz9kaQWwWQ8sxjUZHzUON1chXvjIWQokCAUtDa2j5HKaUvL
0GpJsSselZZRRWx5bShClawtrC8vLdMfEBZ5qxLL4xzY7IIySEH6+SeuIyDZkKmOoI8xFjMz
v0hID+B9s4UEszNPkhU8OdHnHVv7pSp4eqLPG8WtF+zkNF+U1dobFWUW8GS6F1y2pmgqeHKi
L7psFjtcwEMIX2sBXi0paJ8lhSphqHsHEwdjQapeNITwNTp5u+NRf41QhPAxmIWwh0gJZtiq
ujycNTyJ9SukmIwqvnLRCCnBkBsiRrT6UeyKR/NBEPSRg3LUfHzRLNKuPF9vQJrnE+aKQS1j
7A4bY/J8WyN0OG+EGFLh5JOMk1X255LnG8H3XktKMBjLURfs5CxfcsWqd3bCTqZ87HI0UqoK
npzjY4dWq4sKnkz6ikNjkc+CnXt/nByycWtUwUMo39aOXtfg1YyCdpprQCkBvMqhZfPZIY44
282brvY358TDGDhmLNbCRL1kRIYPW4V8vdFQYdlXJz3FY2NVVXBpiIzgZp/N09N2vTMezdWp
+xBrVjlk4zQ5KMMXN+vebs4JiALJ4EhAR3uaNyMe3R8QB4rkJayUvNGW8E0V8sXfETnB/fql
PWAWfr5NCzdvKuE5NzXu79UB+f7z/fuPjx8/39/+eKUPwO3jQ+uX60A+3n754e7x6svt/Q93
V0Ixv9w9PHz37p//vrt79O6v8U/L//6mj867X7/ij5+/XD3It3ff/OHV3f3jl19++7jIA/X0
AJ0enU8f7z9++unT04+PL/Hduz8A3JZ4FG40v7j//Yuf3suvX/vD8WvXa39947c/f/vGP3wA
+TqO1Tffqz9uj8n54/X3dbz+cRmvCePV+OXDbz+s9QOvU8D7q7uf/6PjJvgH/cPLrPsgP7x9
/6AD+PTDf31+/8vTd+8/f//TJ4lYJoj7R/n3z/8FUEsHCGCxhN8UsQMAmJlEAFBLAwQUAAgI
CADju0NSAAAAAAAAAAAAAAAADAAAAHNldHRpbmdzLnhtbO1aW3PaOhB+P78iw+sZijFJWpiE
jiHcWiBgm5vfZFtgJbLksWQM+fWVDWQSavdQsDPtzMlDwLb07Wq12v12zd3XjYuv1tBniJL7
QvmTVLiCxKI2Iqv7wkRvF78Uvtb/uaPLJbJgzaZW4ELCiwxyLoawKzGdsJpFyRKJCYFPahQw
xGoEuJDVuFWjHiSHabW3o2uxsN2dDUbk+b7gcO7VSqUwDD+FlU/UX5XK1Wq1FD89DKWUvg6M
sHeaxYNlSbou7a5fR8dXpyq2X2Ws2P77G9PIhfrBDofl1+/2a9l9FBGHbmSbq/3tSNh9Qahc
WyMYvlqtkDTv/ZwpYsjEUPEh0KlXODzkW088RIQX6tJd6WeQ3wLuwyXPB3mGbO4kQV9/kW4/
XwzfhWjlJKp+U5Xkm8qpAoou8IqI2HAD7WNhMEzepniOcBl/e4rKMOzZR3oy7gsfKNQjjyj/
lqYR6JGeOhAm+S9F30/RHAh5+QQXbAY+o/6IMsTFCZgnmvu8rXyPvEhCrlyfbJv32F3qoxdK
OMCahxEfUBseb4BD/Qu8HPocWXmhH2l/MFGWp/St/jngKxZHaxijq4CsUswjnwd+0DfjyHWA
VdPCyoW42UbwA2qDck7dDIENSl1doGTq0RHoFODgGDVWtCydawOwglF0/SX67ZngmkPDjo+O
A7dJKYaAFOrcD+CZh4NYwpjQ1uGGPwpqscQ07MMVsLZpspYAsxRhCTffJqe0x3EWOfUcx/kl
JYHtEsnFcc7yKcYm8FM5Q+Xz7ckZ/X+HTnPoSEBDcKfnkQ8j6nGGw50ixoA+jfVn2Z+eCH9I
eV7Q+Rz5CLVJMfUT3UW+rcjyzW0G25qDUbqACc0Dl6g07EJgi1IoFyFxIBGRJgf0HnsMuCgf
obZ1TYqZBo/zeyZCYo/vCvaAIwYhomOLRIEz1Z0uOGQ9phHg6VQFjMNjp8pCwA5YrGlXb+Um
QYVMOFdqaVGWP58Z7Y7hE+uLS+G1wLTRGrFU9TMCT1b+XNfZwSsbxLStoCI+Jegl3Uv/bp6z
r+uTBzDIT+/d7G4EPoi86XeaOC3XhCL4ux6GG8FzkMfbgvPkEOZiQQpDgOQvpi/M8AFiHgne
Thi0fykjwyCUcZT4kMSTa7TIkbh8CLHIkS3my1lGoryKthXy4LhtYAIGb68biAB/W6g/j7v/
liQbm+50C2YDPmkNB319ofypf+PydDx58brG7AZbLn7qTxsPelOSE4bOFGWgsNXrdUtRHC36
tMU/za0itdOWFpqyaZKGWPuNZMx7VVWeBsb8m7fYlsdjKeTDlbcWcrBJVMfu4LX5VB6blW+S
5bY9W/GezErDM+aD6mAsvssbtpireDQzHLM7xE237Fiu7Zmu6gAyfbE7ZYEzrg6aYdh/UNhA
iecIfBVbXZWO9J4kdHkxO1PZmIVV8Tw0OsazMTe8hTw5yIjH22Lthi6FTdwYq63hWuiHYSvS
sfV90mkTYzr0oDu5HetjRWn0lLFUHU5a7clcUqeT1qY9a1eHuqS2H8JGy543mDF3hqas4scn
b2S4i/s/kpUJwsHBRot7BypcJpfkZ74ayJ+y5l3aKp4Xpzv/AXDwAYkiS876cbSyT4GtinxB
BTfIYZOVgNMmwFaAAU91ogtpTV50RgNrqDuBaxKA8N/UH9lnu6G4SOkzdiCBPrKKo2a/eCbh
2AsZAQ/6bZ+6ibk1g11oOsAHlpAUkX4fsuioZd6A7CPyPPFs4aPpr5/ObJjm3VGKvHS6e6P+
SJqYsjxide4dkh77Dn0Sl1ujgFg8AAnv0LIQtNvlyGF1KIrIXKJSjz3sfwShCefNpWWlYFH+
x0fwGzWbgFjwjAiVWsWXfvpNRint1yr1H1BLBwivI3eXcwUAAO8iAABQSwMEFAAACAAA47tD
UkFRsCC1BQAAtQUAABgAAABUaHVtYm5haWxzL3RodW1ibmFpbC5wbmeJUE5HDQoaCgAAAA1J
SERSAAAA7QAAAQAIAwAAAGg+AVUAAABaUExURSQkJC0tLTY2Nj09PURERE5OTlNTU1xcXGNj
Y2tra3Nzc3t7e4ODg4uLi5OTk5ubm6SkpKqqqrOzs7u7u8PDw8vLy9TU1Nvb2+Pj4+vr6/Hx
8f7+/gAAAP///+z12t4AAAUWSURBVHja7dxpc+MoEAbgZCwQhyRuJLr////clpOZyW5t1Sie
qj3ilyQOPhr0ABLtL3rhZyov0EILLbTQQgsttND+W1rqv9n/cfyPtLu9/1v//Op6vYEY/1mt
W6p3rm9s+rFGaz8x2MF6O6wN/SU0Y2o3tvDifH1Jv4qU7vqardljWAZb3pyj1Tq6spysn/fd
2kTWub1a2+VJvKrVtXjeoiYdYprGsV9fxoqz3RtNUinHrl0haYvWpK6ELiWP4mOcD1bNUlgn
6uNKr69UXetjCoGnpsaut8D1spZC5LSaHJ0d1czXz8RDc7d5Xl9JkXeLGk6noLyv069jXdNk
vHUxiHZKk/clm/mSVvMxB7N+Wwrb+ur8Rl5vV7WKquUlh2kYw5Hzcn1uJ5KV344XmvjGZUpE
Stoq+wVtm/1QsoBjNO341mdqLcsKuza3xemjv4aNbm0aIxcZr6vahaTTlXfDKXC0/hPnbbIh
dLuFtK3JJRedK9LWwkv4dazpvPpsU+lmWzg6OQPk79IYL24UG9bslrl36/rubP6q+62s5Pf9
wHc1PnlNpg9l0CfL+PFzjx2XGxkfGnh7uNz5iO/djLTU957HpfBBL+pD0eqTRd9D7o/6e7y+
FvihAf0zWF0OlqCfvepL4Vohc/xLuiQb8JEHU5ZKK8zje+XvT6sPycePmnz4Ht4L/c7BjvxQ
okqyG1PpV7RJyfVaJ3XoNLfogiEllSAVaYLorhsnctwrZOQlenur3985r7+vxDrOVa7h5t79
g2aV7QOJ5jA3Zp3MfkE78spr5nXxXL0erGVDloocPvFtUd4Zmr3e9SJbgfZzf8nBurVNy3Qo
ye30uaENTd1KTi2JhPxyNutjV2NFaXsgTNKB5lK9tJLLyr5x1OeWrIjnTVJcK7mhyCW72Fil
RVKxeefJNrbtTDT4diYsRe0z70dtfGYwi2RAEm5b7UfOj82tm6eHlvLEeapzuaI957ZIJuBl
gM4pTefcynGfv+dXGCXispx2WSvuXdu8BEn6K6f8lk5tdzJYkhnObZP1/Nj3xHPwzGNa+Sog
s/Zr7b7Z3nVVh6qmhiXLeVvlkNdkzlZiYLWrbqpApuj7RLfd5Dy/acdUJWViard6qGJL9HmW
JnV9bG7H1LflgTDpfshB1wvavEn22sPOR5AlmSP9rHDmvp8P8kI+nxX5WC2UIh2V25Hlo+fZ
MrZt2+/VEs/L1vHg3PIeHhmmXbofb0eC/RZaaKGFFlpooYUWWmihhRZaaKGFFlpooYUWWmih
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
--------------4B194FF8F3EA3786FF9EAE1F
Content-Type: application/x-compressed-tar;
 name="brin-stress-test.tgz"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
 filename="brin-stress-test.tgz"

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
4sSJE/vk/y10LU4AkAEA
--------------4B194FF8F3EA3786FF9EAE1F
Content-Type: application/x-compressed-tar;
 name="brin-bench.tgz"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
 filename="brin-bench.tgz"

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
--------------4B194FF8F3EA3786FF9EAE1F--





^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/9] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 4e0c9be58c..4099e72001 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8191,7 +8191,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------0E72B707603BED22B4040825--





^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/9] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 1487710d59..33841e14f2 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8191,7 +8191,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------22A4B241170149838D4D1F8F
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210215.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210215.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 58fe109d2d..8a1a9da78f 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -389,6 +389,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -410,6 +413,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -470,7 +528,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -480,51 +538,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index d7b55f57ea..871e024e00 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8143,7 +8143,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8159,7 +8159,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------CF71AF65F7C337C37C24B045
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210112.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210112.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/6] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 58fe109d2d..8a1a9da78f 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -389,6 +389,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -410,6 +413,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -470,7 +528,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -480,51 +538,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index d7b55f57ea..871e024e00 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8143,7 +8143,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8159,7 +8159,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------D21F32E0F9E7408E9BE1AF2E
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210114.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210114.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/6] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index d27336adcd..f3ead7d53d 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8145,7 +8145,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8161,7 +8161,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------310A2AE1CC4C2E2E77559E3D
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-suppo-20210114-2.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-suppo-20210114-2.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index b5f52d4e4a..2ef11245a8 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8183,7 +8183,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8199,7 +8199,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------FA974B75A0C3E9CA18CE7207
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210122.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210122.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/6] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 158 ++++++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 140 ++++++++++++++------
 src/backend/access/brin/brin_minmax.c    |  92 ++++++++++---
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 303 insertions(+), 95 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..963b7079cf 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,78 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of
+					 * multiple scan keys. We can determine that based on the
+					 * number of arguments - functions with extra parameter
+					 * (number of scan keys) do support this, otherwise we
+					 * have to simply pass the scan keys one by one, as
+					 * before.
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same
+						 * for all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet
+						 * the criteria for a single one of them is enough to
+						 * discard the range as a whole, so break out of the
+						 * loop as soon as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+
+							/* mismatching key, no need to look further  */
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..a260074c91 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -251,6 +253,10 @@ brin_inclusion_add_value(PG_FUNCTION_ARGS)
 /*
  * BRIN inclusion consistent function
  *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
+ *
  * All of the strategies are optional.
  */
 Datum
@@ -258,24 +264,31 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/* Handle IS NULL/IS NOT NULL tests */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -284,7 +297,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -293,7 +311,14 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
@@ -301,10 +326,45 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all regular scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* Skip IS NULL/IS NOT NULL keys (already handled above). */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
+	/* This should be called only for regular keys, not for IS [NOT] NULL. */
+	Assert(!(key->sk_flags & SK_ISNULL));
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +384,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +444,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +464,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +483,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +518,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +528,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..e116084a02 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -140,29 +142,41 @@ brin_minmax_add_value(PG_FUNCTION_ARGS)
  * Given an index tuple corresponding to a certain page range and a scan key,
  * return whether the scan key is consistent with the index tuple's min/max
  * values.  Return true if so, false otherwise.
+ *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
  */
 Datum
 brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
 	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -171,7 +185,12 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -180,13 +199,52 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
+	}
+
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
+
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +287,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 1487710d59..33841e14f2 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8191,7 +8191,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------6A37408A2C42B5B56C3B3D49
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210303.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210303.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c          | 158 +++++++++++++++++++-----
 src/backend/access/brin/brin_validate.c |   4 +-
 2 files changed, 126 insertions(+), 36 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..963b7079cf 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,78 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of
+					 * multiple scan keys. We can determine that based on the
+					 * number of arguments - functions with extra parameter
+					 * (number of scan keys) do support this, otherwise we
+					 * have to simply pass the scan keys one by one, as
+					 * before.
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same
+						 * for all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet
+						 * the criteria for a single one of them is enough to
+						 * discard the range as a whole, so break out of the
+						 * loop as soon as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+
+							/* mismatching key, no need to look further  */
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-- 
2.26.2


--------------AC3FFB734F56C5F52D422EFC
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Process-all-scan-keys-in-existing-BRIN-opcl-20210305.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Process-all-scan-keys-in-existing-BRIN-opcl-20210305.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c          | 158 +++++++++++++++++++-----
 src/backend/access/brin/brin_validate.c |   4 +-
 2 files changed, 126 insertions(+), 36 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..f9a0476024 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,78 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any scan keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of
+					 * multiple scan keys. We can determine that based on the
+					 * number of arguments - functions with extra parameter
+					 * (number of scan keys) do support this, otherwise we
+					 * have to simply pass the scan keys one by one, as
+					 * before.
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same
+						 * for all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet
+						 * the criteria for a single one of them is enough to
+						 * discard the range as a whole, so break out of the
+						 * loop as soon as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+
+							/* mismatching key, no need to look further  */
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-- 
2.26.2


--------------82D677E9F94AC7574E460205
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Process-all-scan-keys-in-existing-BRIN-opcl-20210308.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Process-all-scan-keys-in-existing-BRIN-opcl-20210308.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c          | 158 +++++++++++++++++++-----
 src/backend/access/brin/brin_validate.c |   4 +-
 2 files changed, 126 insertions(+), 36 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..f9a0476024 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,78 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any scan keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of
+					 * multiple scan keys. We can determine that based on the
+					 * number of arguments - functions with extra parameter
+					 * (number of scan keys) do support this, otherwise we
+					 * have to simply pass the scan keys one by one, as
+					 * before.
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same
+						 * for all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet
+						 * the criteria for a single one of them is enough to
+						 * discard the range as a whole, so break out of the
+						 * loop as soon as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+
+							/* mismatching key, no need to look further  */
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-- 
2.26.2


--------------556A1DC61262AF15641DB204
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Process-all-scan-keys-in-existing-BRIN-opc-20210308b.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Process-all-scan-keys-in-existing-BRIN-opc-20210308b.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow future opclases to benefit from seeing all keys at once.

This does break existing BRIN opclasses, because the signature of the
consistent function changed. We might support both variants (with 3 and
4 parameters), but that seems pointless - the changes to NULL handling
likely require updates too. So better to make the failure clear. Also,
we're not aware of any out-of-core opclasses - there may be some, but
probably not many.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 doc/src/sgml/brin.sgml                   |   8 +-
 src/backend/access/brin/brin.c           | 118 +++++++++++++------
 src/backend/access/brin/brin_inclusion.c | 140 ++++++++++++++++-------
 src/backend/access/brin/brin_minmax.c    |  92 ++++++++++++---
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 6 files changed, 269 insertions(+), 97 deletions(-)

diff --git a/doc/src/sgml/brin.sgml b/doc/src/sgml/brin.sgml
index 06880c0f7b..078f51bb55 100644
--- a/doc/src/sgml/brin.sgml
+++ b/doc/src/sgml/brin.sgml
@@ -464,12 +464,14 @@ typedef struct BrinOpcInfo
 
    <varlistentry>
     <term><function>bool consistent(BrinDesc *bdesc, BrinValues *column,
-       ScanKey key)</function></term>
+       ScanKey *keys, int nkeys)</function></term>
     <listitem>
      <para>
-      Returns whether the ScanKey is consistent with the given indexed
-      values for a range.
+      Returns whether all the ScanKey entries are consistent with the given
+      indexed values for a range.
       The attribute number to use is passed as part of the scan key.
+      Multiple scan keys for the same attribute may be passed at once, the
+      number of entries is determined by the <literal>nkeys</literal> parameter.
      </para>
     </listitem>
    </varlistentry>
diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..743f2a925a 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,40 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
+					Oid			collation;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
-
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
-
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					/* skip attributes without any scan keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
+
+					bval = &dtup->bt_columns[attno - 1];
+
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * XXX We simply use the collation from the first key (it
+					 * has to be the same for all keys for the same attribue).
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
+					collation = keys[attno - 1][0]->sk_collation;
+
+					/* Check all keys at once */
+					add = FunctionCall4Coll(&consistentFn[attno - 1],
+											collation,
 											PointerGetDatum(bdesc),
 											PointerGetDatum(bval),
-											PointerGetDatum(key));
+											PointerGetDatum(keys[attno - 1]),
+											Int32GetDatum(nkeys[attno - 1]));
 					addrange = DatumGetBool(add);
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..a260074c91 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -251,6 +253,10 @@ brin_inclusion_add_value(PG_FUNCTION_ARGS)
 /*
  * BRIN inclusion consistent function
  *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
+ *
  * All of the strategies are optional.
  */
 Datum
@@ -258,24 +264,31 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/* Handle IS NULL/IS NOT NULL tests */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -284,7 +297,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -293,7 +311,14 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
@@ -301,10 +326,45 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all regular scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* Skip IS NULL/IS NOT NULL keys (already handled above). */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
+	/* This should be called only for regular keys, not for IS [NOT] NULL. */
+	Assert(!(key->sk_flags & SK_ISNULL));
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +384,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +444,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +464,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +483,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +518,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +528,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..e116084a02 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -140,29 +142,41 @@ brin_minmax_add_value(PG_FUNCTION_ARGS)
  * Given an index tuple corresponding to a certain page range and a scan key,
  * return whether the scan key is consistent with the index tuple's min/max
  * values.  Return true if so, false otherwise.
+ *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
  */
 Datum
 brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
 	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -171,7 +185,12 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -180,13 +199,52 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
+	}
+
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
+
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +287,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..2c4f9a3eff 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											4, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index c7619f8cd3..cd1eda38ab 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8223,7 +8223,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------D524CD37E77B36A2883A7617
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Move-IS-NOT-NULL-handling-from-BRIN-support-20210311.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Move-IS-NOT-NULL-handling-from-BRIN-support-20210311.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/9] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 4e0c9be58c..4099e72001 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8191,7 +8191,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------4B194FF8F3EA3786FF9EAE1F
Content-Type: application/vnd.oasis.opendocument.spreadsheet;
 name="brin-bench.ods"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
 filename="brin-bench.ods"

UEsDBBQAAAgAAOO7Q1KFbDmKLgAAAC4AAAAIAAAAbWltZXR5cGVhcHBsaWNhdGlvbi92bmQu
b2FzaXMub3BlbmRvY3VtZW50LnNwcmVhZHNoZWV0UEsDBBQAAAgAAOO7Q1IAAAAAAAAAAAAA
AAAcAAAAQ29uZmlndXJhdGlvbnMyL2FjY2VsZXJhdG9yL1BLAwQUAAAIAADju0NSAAAAAAAA
AAAAAAAAHwAAAENvbmZpZ3VyYXRpb25zMi9pbWFnZXMvQml0bWFwcy9QSwMEFAAACAAA47tD
UgAAAAAAAAAAAAAAABgAAABDb25maWd1cmF0aW9uczIvdG9vbGJhci9QSwMEFAAACAAA47tD
UgAAAAAAAAAAAAAAABgAAABDb25maWd1cmF0aW9uczIvZmxvYXRlci9QSwMEFAAACAAA47tD
UgAAAAAAAAAAAAAAABoAAABDb25maWd1cmF0aW9uczIvcG9wdXBtZW51L1BLAwQUAAAIAADj
u0NSAAAAAAAAAAAAAAAAGAAAAENvbmZpZ3VyYXRpb25zMi9tZW51YmFyL1BLAwQUAAAIAADj
u0NSAAAAAAAAAAAAAAAAGgAAAENvbmZpZ3VyYXRpb25zMi90b29scGFuZWwvUEsDBBQAAAgA
AOO7Q1IAAAAAAAAAAAAAAAAaAAAAQ29uZmlndXJhdGlvbnMyL3N0YXR1c2Jhci9QSwMEFAAA
CAAA47tDUgAAAAAAAAAAAAAAABwAAABDb25maWd1cmF0aW9uczIvcHJvZ3Jlc3NiYXIvUEsD
BBQACAgIAOO7Q1IAAAAAAAAAAAAAAAAMAAAAbWFuaWZlc3QucmRmzZPNboMwEITvPIVlzthA
LwUFcijKuWqfwDWGWAUv8poS3r6Ok1ZRpKrqn9TjrkYz3460m+1hHMiLsqjBVDRjKSXKSGi1
6Ss6uy65pds62ti2Kx+aHfFqg6WfKrp3bio5X5aFLTcMbM+zoih4mvM8T7wiwdU4cUgMxrSO
CAkejUJp9eR8GjnO4glmV1F066CQefcgPYvdOqmgsgphtlK9h7YgkYFAjQlMyoR0gxy6TkvF
M5bzUTnBoe3ix2C904OiPGDwK47P2N6IDKblXuC9sO5cg998lWh67mN6ddPF8d8jlGCcMu5P
6rs7ef/n/i7P/xnir7R2RGxAzqNn+pDntPIfVUevUEsHCLT3aNIFAQAAgwMAAFBLAwQUAAgI
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
qj3ilyQOPhr0ABLtL3rhZyov0EILLbTQQgsttND+W1rqv9n/cfyPtLu9/1v//Op6vYEY/1mt
W6p3rm9s+rFGaz8x2MF6O6wN/SU0Y2o3tvDifH1Jv4qU7vqardljWAZb3pyj1Tq6spysn/fd
2kTWub1a2+VJvKrVtXjeoiYdYprGsV9fxoqz3RtNUinHrl0haYvWpK6ELiWP4mOcD1bNUlgn
6uNKr69UXetjCoGnpsaut8D1spZC5LSaHJ0d1czXz8RDc7d5Xl9JkXeLGk6noLyv069jXdNk
vHUxiHZKk/clm/mSVvMxB7N+Wwrb+ur8Rl5vV7WKquUlh2kYw5Hzcn1uJ5KV344XmvjGZUpE
Stoq+wVtm/1QsoBjNO341mdqLcsKuza3xemjv4aNbm0aIxcZr6vahaTTlXfDKXC0/hPnbbIh
dLuFtK3JJRedK9LWwkv4dazpvPpsU+lmWzg6OQPk79IYL24UG9bslrl36/rubP6q+62s5Pf9
wHc1PnlNpg9l0CfL+PFzjx2XGxkfGnh7uNz5iO/djLTU957HpfBBL+pD0eqTRd9D7o/6e7y+
FvihAf0zWF0OlqCfvepL4Vohc/xLuiQb8JEHU5ZKK8zje+XvT6sPycePmnz4Ht4L/c7BjvxQ
okqyG1PpV7RJyfVaJ3XoNLfogiEllSAVaYLorhsnctwrZOQlenur3985r7+vxDrOVa7h5t79
g2aV7QOJ5jA3Zp3MfkE78spr5nXxXL0erGVDloocPvFtUd4Zmr3e9SJbgfZzf8nBurVNy3Qo
ye30uaENTd1KTi2JhPxyNutjV2NFaXsgTNKB5lK9tJLLyr5x1OeWrIjnTVJcK7mhyCW72Fil
RVKxeefJNrbtTDT4diYsRe0z70dtfGYwi2RAEm5b7UfOj82tm6eHlvLEeapzuaI957ZIJuBl
gM4pTefcynGfv+dXGCXispx2WSvuXdu8BEn6K6f8lk5tdzJYkhnObZP1/Nj3xHPwzGNa+Sog
s/Zr7b7Z3nVVh6qmhiXLeVvlkNdkzlZiYLWrbqpApuj7RLfd5Dy/acdUJWViard6qGJL9HmW
JnV9bG7H1LflgTDpfshB1wvavEn22sPOR5AlmSP9rHDmvp8P8kI+nxX5WC2UIh2V25Hlo+fZ
MrZt2+/VEs/L1vHg3PIeHhmmXbofb0eC/RZaaKGFFlpooYUWWmihhRZaaKGFFlpooYUWWmih
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
--------------4B194FF8F3EA3786FF9EAE1F
Content-Type: application/x-compressed-tar;
 name="brin-stress-test.tgz"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
 filename="brin-stress-test.tgz"

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
4sSJE/vk/y10LU4AkAEA
--------------4B194FF8F3EA3786FF9EAE1F
Content-Type: application/x-compressed-tar;
 name="brin-bench.tgz"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
 filename="brin-bench.tgz"

H4sIAAAAAAAAA+2d33PqxhmGfWv9FVsfpoYWjiUsMIPjzJyLpDedpJM07UVPBwu0gOaApEjC
dtP0f+9KwjY/LGnF0aJd825mYicSQnpY8ejVh/nGgeN2xtSdzK/G8a+OS6OO4z+YH8P5WUVD
Z+PGNJOfht7f+qnrfVO/vjkzTF3vXfe6va5xpht9s989I3pVO5A3VmFkBYSc+V4YzQIaZq1X
tFzR8eEPV2PHvRpb4VzTfvjpx3/+fNcwtL99+st37Jeu9o9Pf/0l/u1a++mXH36+62maHXi+
PSadjjPt0CcnjEIS0TDSJgG1IsqWJP+l+eGvi+RX8i25sunDlbtaLEj32z8a5Jtvvvvx+/X6
ZLpyJ5HjuSSwXNtbjhy/6Y8erAVx3KhFAhqtAjck8awkVkg+Nz43tDGdOa5G2EgXk0uje/NR
Z/8Yl8NhsuqfSbKRW4269q0WP4osLHe2smaU+At/xnbuVov3QvtAlp7rRZ7rTNrsGSbsAY47
ayfPuHkUnQm5WO/yyl14sxm1SWSNF5REpGklq7cu9o51ZwOOG9Igig/NYw8L6YJOoo0Dd1pk
GnhLMqMuDdgzjdjaDg2bRruRvDItErJ1Cp/lwZqsVktiudbiP7+x/St8wGROJ198j+3WG6tq
4d19snqHrfzp9UHrvfdno8iLrMUooAsrfiFHofMbbV5Gl62Le02begEJ2AGT+5D+SgzSiKfR
/S2xPU07/8BewNlqwU6/cRRQylaz6ZN2vjl14vekj9HSX0+az5GzZC/P8+RJHkAc+4mwCRS/
Dq3bZH6+Lli/yufR3T07eX3yd2dJXzf6O5lTyyYdl+3Z78R6/EIu/+uzhRFpdP93yXb/nE7m
3usM6bAJQl7eIdd7nb42pJGcM6SRnjGkEZJGQBpRcpjxExK240vr6asPchWyZekW2fGSRyea
k6bPJnY48mkwYrOJzfG79e4cmUcskPVhclNZLSJHCJtkx0bplkfJ04w8P2yyt4XVLqt071oy
0oz3uyzT8cJj7yICYCYbjilKSCo96CJEtufS3bf1ZE/X7+VvvQHmOqJNfMu2qV3SFW0Si/Kp
Cme0ydLuNZ3hMNkeDKKQQTrp3IFIMrDAJ6KgQivlgB3LLjaVM4KkR9422h0DDqnbIfEkQQzJ
AQJvVI8TxuBFVZcr1IgiMIm0JkEcKeACrwijCr2UJCbOMh8qGju6MnSd2E4YOS57m01naT0Z
Z+nZTafNdqeFu2WS+4m9SKi5FDOBl4QQhZNK0DpW6ok18mwPyWoxG2JBUUZpzSAJFaOBdESC
hXvKQzumgvaSTN2Vm8JUgxtvkhkHZRwOKLCMGKTwSxlcUplFjphDuHMOxCO1eJB1ONhAQ0LJ
wkYHUFOxAiRdDQhVICWchToQHxV4ShBTGKoUryMGJgXqQagIvQPlICfxwIGAxKKFhw7Bdlwd
yVsbQnVIIfugPsSFBcYRBRWuKQdMMsvIEX9IifwDCUkuIWQgLjpQkmC2MNNB3NSoGKUGkegP
hprxnvxp/T+arVb8JXO4hSenv9IXKT4VEJ0yYMBO1aKEjHgwCQ1Hm8rYNEXdEehtc6AUpKZH
Tj395DKBVYQQhVxK0FIu38iUcJBx1HMTUk4ODhipapiQER+oY2UdCdMO8s57cgoSTy4VGEYQ
U4imFC9xvqm7PRGG4JHOn/3+X/0j9v8y9I3+X+ZN0v/rBv2/jjKk7f81dmalWoCxmTQ0p4Ph
9XBsDbtUHw6M6XQ4pd3u0DamxpXRHex0B2MXqkY6BdEnDNfQwhpJ9E/26jmTB66bK6eJK2ZO
UugThrswqhnk1G/DFGGBT0RBhVbKAUOfMPwFhzQO2fokOGLIPhB4o3qcMAYvKvQJw98CKmkS
xJECLvCKMKrQS0lianwmFn3C4KevmP+7fSEQdt5kAi8JIQonlaCFPmHoE/ZuNIMkVIwG0hEJ
Fu4pD02qbi7SpRrceJPMOCjjcECBZcQghV/K4JLKLHLEHPQJeyfiQdbhYAMNCSULGx1ATcUK
kHQ1IFSBlHAW6kB8VOApQUxhqFK80CcMfcLemXKQk3jgQEBi0cJDh2CTrIOLhGkHN+mksw/q
Q1xYYBxRUOGacsAks4wc8Qd9wt6RhJCBuOhASYLZwkwHcVOjYoQ+YfBXlb0kTjc6vQ0DdqoW
JWTEgwl9wvC9+Yp75NTTTy4TWEUIUcilBC3l8o1MCQcZRz03IeXk4ICRqoYJGfGBQp8w5J13
4RQknlwqMIwgphBNKV7oE4axM9J5sdn/KzIrbP2VjIL+X93e9fVL/y+zZ5zpRq/XRf+vowxR
/b+ye6FEZqnrzkMvNx1cP8p4/bjbRCE63b7lb6GQ7UoxMhW4UswEKc/lIeMozcd/tiHV0g8r
Mg+6B/G1tyAc3GFQ0RCnfnchhwh8IYAntMHNqp4eJvVGCPz1gUSOWH+KGTFimwW8UClJGIGD
Ul0ukDdKwBQymgJxIhsJvCECKPTBD0uNz2YW96s6UkZ5/Tp33M2S2z+vPQkQVvZwwDtVw4Rz
+EDV3o+qpgDzKg4URVTVCJJMLhVIRRBTuKUUL4m6gkiSSnBjTDKjoIySyQMWqZwm/MFJSipz
1BhTCG9OgVhkFQuySj4WaEYUVNimHDAVKzBy1GBQhVHBSajD5AGBh6rHCQPxopKgH1Td9RhU
ZJRWCnJOARcIRhhVeKYkMak6cUiTVnATTTq7oD6TQwRGEcATLuFmJZlFaq7ToFKjvGSQYYrA
QDnisMI8ZZGpUbEp6Nd0pPiz3WkD99ZkFNPWF/ifcObZ4wDtVEYRlikgVEMjppqyy7YSUHxR
ThCnnleycEAXVcOENfhAKZdI6s4kSCUKSQe5ZI8EVFMhR1imkFEtrZPqyydIKKrLAhklCwjU
UT1OGIQX1Yn3REoZbPX/GRy7/0/f2Oj/c6On/X/66P9zjFFD/59BiYunsTM7PFajBZCUl0Z7
Xyk/ONmLordQSHc5NFDgcigTpEQXQoO6L4SyINXTAmhwQJZOdYAuQKcoiVMP0DlEoAwBPGEO
blY1dX6oO0jgI+wSaeL5k7EIE1ssoIZKSUIKHJTq0oHUgQKykFEWCBXZSKAOEUBhEH5YanyK
kKMX0NGSCtoBqaKgjW+LR2TZxQH1VA0T2uEDVX87oNpiDDoCqW8S5JlcKvCKIKbQSyleMvV1
kCab4A6ZZFJBSSWTB0RSOU0ohJOUVPKoN6ygL5DybkFiyccC04iCCuGUA6ZiNUaaegwqMipo
CTWZPCBQUfU4ISFeVDK0Bqq/NoPqjNJWQdop4ALHCKMK1ZQkJldfB4kyC+6mSScY1GpyiEAq
AnhCJ9ysJBNJ/TUbVG2U9wySTBEYWEccVsinLDI1qjdFPYKOFoLQJkh+N21/Af3pJp89DjBP
ZRQhmgJCdbQJqi3BoFOQ4o449dSShQPGqBomxMEHSrlcIkEyQTZRyDtIJ3skYJsKOUI0hYzq
aRZUZ0pBTlHdF0gqWUBgj+pxQiK8qN5Zv6D0mF76/1Td+icZ+f1/2DLdfOn/cxP/f8Psmwb6
/xxjbPX/yejtsz9Xt5r9vDGVHzN8PvceSfxG6VuBtVjQxWhpsROMupY7oaNHL/hCgzBWujMl
/yIXjccLdrJScqFfkH/fkmhO3fUpesESeHIiPW+IbGyIPG+IrfzksMshbepsXCUk57W+/qGv
LxPipX6ytE/6JjG6g/WCZMlDvGRArrubC84/vnTMMtlpk5z5Pmk8bC8abC3aWkajjuM/ZD82
Xd7f3UD61rL+kfy77jmEgYGBgYGBgYGBgaHG+D9xSRWUALgBAA==
--------------4B194FF8F3EA3786FF9EAE1F--





^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/9] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 4e0c9be58c..4099e72001 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8191,7 +8191,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------0E72B707603BED22B4040825--





^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/9] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 1487710d59..33841e14f2 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8191,7 +8191,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------22A4B241170149838D4D1F8F
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210215.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210215.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 58fe109d2d..8a1a9da78f 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -389,6 +389,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -410,6 +413,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -470,7 +528,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -480,51 +538,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index d7b55f57ea..871e024e00 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8143,7 +8143,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8159,7 +8159,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------CF71AF65F7C337C37C24B045
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210112.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210112.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/6] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 58fe109d2d..8a1a9da78f 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -389,6 +389,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -410,6 +413,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -470,7 +528,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -480,51 +538,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index d7b55f57ea..871e024e00 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8143,7 +8143,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8159,7 +8159,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------D21F32E0F9E7408E9BE1AF2E
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210114.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210114.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/6] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index d27336adcd..f3ead7d53d 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8145,7 +8145,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8161,7 +8161,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------310A2AE1CC4C2E2E77559E3D
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-suppo-20210114-2.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-suppo-20210114-2.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index b5f52d4e4a..2ef11245a8 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8183,7 +8183,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8199,7 +8199,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------FA974B75A0C3E9CA18CE7207
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210122.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210122.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/6] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 158 ++++++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 140 ++++++++++++++------
 src/backend/access/brin/brin_minmax.c    |  92 ++++++++++---
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 303 insertions(+), 95 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..963b7079cf 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,78 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of
+					 * multiple scan keys. We can determine that based on the
+					 * number of arguments - functions with extra parameter
+					 * (number of scan keys) do support this, otherwise we
+					 * have to simply pass the scan keys one by one, as
+					 * before.
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same
+						 * for all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet
+						 * the criteria for a single one of them is enough to
+						 * discard the range as a whole, so break out of the
+						 * loop as soon as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+
+							/* mismatching key, no need to look further  */
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..a260074c91 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -251,6 +253,10 @@ brin_inclusion_add_value(PG_FUNCTION_ARGS)
 /*
  * BRIN inclusion consistent function
  *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
+ *
  * All of the strategies are optional.
  */
 Datum
@@ -258,24 +264,31 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/* Handle IS NULL/IS NOT NULL tests */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -284,7 +297,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -293,7 +311,14 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
@@ -301,10 +326,45 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all regular scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* Skip IS NULL/IS NOT NULL keys (already handled above). */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
+	/* This should be called only for regular keys, not for IS [NOT] NULL. */
+	Assert(!(key->sk_flags & SK_ISNULL));
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +384,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +444,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +464,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +483,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +518,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +528,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..e116084a02 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -140,29 +142,41 @@ brin_minmax_add_value(PG_FUNCTION_ARGS)
  * Given an index tuple corresponding to a certain page range and a scan key,
  * return whether the scan key is consistent with the index tuple's min/max
  * values.  Return true if so, false otherwise.
+ *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
  */
 Datum
 brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
 	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -171,7 +185,12 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -180,13 +199,52 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
+	}
+
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
+
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +287,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 1487710d59..33841e14f2 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8191,7 +8191,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------6A37408A2C42B5B56C3B3D49
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210303.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210303.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c          | 158 +++++++++++++++++++-----
 src/backend/access/brin/brin_validate.c |   4 +-
 2 files changed, 126 insertions(+), 36 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..963b7079cf 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,78 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of
+					 * multiple scan keys. We can determine that based on the
+					 * number of arguments - functions with extra parameter
+					 * (number of scan keys) do support this, otherwise we
+					 * have to simply pass the scan keys one by one, as
+					 * before.
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same
+						 * for all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet
+						 * the criteria for a single one of them is enough to
+						 * discard the range as a whole, so break out of the
+						 * loop as soon as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+
+							/* mismatching key, no need to look further  */
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-- 
2.26.2


--------------AC3FFB734F56C5F52D422EFC
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Process-all-scan-keys-in-existing-BRIN-opcl-20210305.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Process-all-scan-keys-in-existing-BRIN-opcl-20210305.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c          | 158 +++++++++++++++++++-----
 src/backend/access/brin/brin_validate.c |   4 +-
 2 files changed, 126 insertions(+), 36 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..f9a0476024 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,78 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any scan keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of
+					 * multiple scan keys. We can determine that based on the
+					 * number of arguments - functions with extra parameter
+					 * (number of scan keys) do support this, otherwise we
+					 * have to simply pass the scan keys one by one, as
+					 * before.
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same
+						 * for all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet
+						 * the criteria for a single one of them is enough to
+						 * discard the range as a whole, so break out of the
+						 * loop as soon as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+
+							/* mismatching key, no need to look further  */
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-- 
2.26.2


--------------82D677E9F94AC7574E460205
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Process-all-scan-keys-in-existing-BRIN-opcl-20210308.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Process-all-scan-keys-in-existing-BRIN-opcl-20210308.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c          | 158 +++++++++++++++++++-----
 src/backend/access/brin/brin_validate.c |   4 +-
 2 files changed, 126 insertions(+), 36 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..f9a0476024 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,78 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any scan keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of
+					 * multiple scan keys. We can determine that based on the
+					 * number of arguments - functions with extra parameter
+					 * (number of scan keys) do support this, otherwise we
+					 * have to simply pass the scan keys one by one, as
+					 * before.
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same
+						 * for all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet
+						 * the criteria for a single one of them is enough to
+						 * discard the range as a whole, so break out of the
+						 * loop as soon as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+
+							/* mismatching key, no need to look further  */
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-- 
2.26.2


--------------556A1DC61262AF15641DB204
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Process-all-scan-keys-in-existing-BRIN-opc-20210308b.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Process-all-scan-keys-in-existing-BRIN-opc-20210308b.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow future opclases to benefit from seeing all keys at once.

This does break existing BRIN opclasses, because the signature of the
consistent function changed. We might support both variants (with 3 and
4 parameters), but that seems pointless - the changes to NULL handling
likely require updates too. So better to make the failure clear. Also,
we're not aware of any out-of-core opclasses - there may be some, but
probably not many.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 doc/src/sgml/brin.sgml                   |   8 +-
 src/backend/access/brin/brin.c           | 118 +++++++++++++------
 src/backend/access/brin/brin_inclusion.c | 140 ++++++++++++++++-------
 src/backend/access/brin/brin_minmax.c    |  92 ++++++++++++---
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 6 files changed, 269 insertions(+), 97 deletions(-)

diff --git a/doc/src/sgml/brin.sgml b/doc/src/sgml/brin.sgml
index 06880c0f7b..078f51bb55 100644
--- a/doc/src/sgml/brin.sgml
+++ b/doc/src/sgml/brin.sgml
@@ -464,12 +464,14 @@ typedef struct BrinOpcInfo
 
    <varlistentry>
     <term><function>bool consistent(BrinDesc *bdesc, BrinValues *column,
-       ScanKey key)</function></term>
+       ScanKey *keys, int nkeys)</function></term>
     <listitem>
      <para>
-      Returns whether the ScanKey is consistent with the given indexed
-      values for a range.
+      Returns whether all the ScanKey entries are consistent with the given
+      indexed values for a range.
       The attribute number to use is passed as part of the scan key.
+      Multiple scan keys for the same attribute may be passed at once, the
+      number of entries is determined by the <literal>nkeys</literal> parameter.
      </para>
     </listitem>
    </varlistentry>
diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..743f2a925a 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,40 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
+					Oid			collation;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
-
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
-
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					/* skip attributes without any scan keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
+
+					bval = &dtup->bt_columns[attno - 1];
+
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * XXX We simply use the collation from the first key (it
+					 * has to be the same for all keys for the same attribue).
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
+					collation = keys[attno - 1][0]->sk_collation;
+
+					/* Check all keys at once */
+					add = FunctionCall4Coll(&consistentFn[attno - 1],
+											collation,
 											PointerGetDatum(bdesc),
 											PointerGetDatum(bval),
-											PointerGetDatum(key));
+											PointerGetDatum(keys[attno - 1]),
+											Int32GetDatum(nkeys[attno - 1]));
 					addrange = DatumGetBool(add);
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..a260074c91 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -251,6 +253,10 @@ brin_inclusion_add_value(PG_FUNCTION_ARGS)
 /*
  * BRIN inclusion consistent function
  *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
+ *
  * All of the strategies are optional.
  */
 Datum
@@ -258,24 +264,31 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/* Handle IS NULL/IS NOT NULL tests */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -284,7 +297,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -293,7 +311,14 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
@@ -301,10 +326,45 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all regular scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* Skip IS NULL/IS NOT NULL keys (already handled above). */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
+	/* This should be called only for regular keys, not for IS [NOT] NULL. */
+	Assert(!(key->sk_flags & SK_ISNULL));
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +384,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +444,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +464,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +483,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +518,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +528,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..e116084a02 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -140,29 +142,41 @@ brin_minmax_add_value(PG_FUNCTION_ARGS)
  * Given an index tuple corresponding to a certain page range and a scan key,
  * return whether the scan key is consistent with the index tuple's min/max
  * values.  Return true if so, false otherwise.
+ *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
  */
 Datum
 brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
 	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -171,7 +185,12 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -180,13 +199,52 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
+	}
+
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
+
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +287,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..2c4f9a3eff 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											4, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index c7619f8cd3..cd1eda38ab 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8223,7 +8223,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------D524CD37E77B36A2883A7617
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Move-IS-NOT-NULL-handling-from-BRIN-support-20210311.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Move-IS-NOT-NULL-handling-from-BRIN-support-20210311.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/9] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 4e0c9be58c..4099e72001 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8191,7 +8191,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------4B194FF8F3EA3786FF9EAE1F
Content-Type: application/vnd.oasis.opendocument.spreadsheet;
 name="brin-bench.ods"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
 filename="brin-bench.ods"

UEsDBBQAAAgAAOO7Q1KFbDmKLgAAAC4AAAAIAAAAbWltZXR5cGVhcHBsaWNhdGlvbi92bmQu
b2FzaXMub3BlbmRvY3VtZW50LnNwcmVhZHNoZWV0UEsDBBQAAAgAAOO7Q1IAAAAAAAAAAAAA
AAAcAAAAQ29uZmlndXJhdGlvbnMyL2FjY2VsZXJhdG9yL1BLAwQUAAAIAADju0NSAAAAAAAA
AAAAAAAAHwAAAENvbmZpZ3VyYXRpb25zMi9pbWFnZXMvQml0bWFwcy9QSwMEFAAACAAA47tD
UgAAAAAAAAAAAAAAABgAAABDb25maWd1cmF0aW9uczIvdG9vbGJhci9QSwMEFAAACAAA47tD
UgAAAAAAAAAAAAAAABgAAABDb25maWd1cmF0aW9uczIvZmxvYXRlci9QSwMEFAAACAAA47tD
UgAAAAAAAAAAAAAAABoAAABDb25maWd1cmF0aW9uczIvcG9wdXBtZW51L1BLAwQUAAAIAADj
u0NSAAAAAAAAAAAAAAAAGAAAAENvbmZpZ3VyYXRpb25zMi9tZW51YmFyL1BLAwQUAAAIAADj
u0NSAAAAAAAAAAAAAAAAGgAAAENvbmZpZ3VyYXRpb25zMi90b29scGFuZWwvUEsDBBQAAAgA
AOO7Q1IAAAAAAAAAAAAAAAAaAAAAQ29uZmlndXJhdGlvbnMyL3N0YXR1c2Jhci9QSwMEFAAA
CAAA47tDUgAAAAAAAAAAAAAAABwAAABDb25maWd1cmF0aW9uczIvcHJvZ3Jlc3NiYXIvUEsD
BBQACAgIAOO7Q1IAAAAAAAAAAAAAAAAMAAAAbWFuaWZlc3QucmRmzZPNboMwEITvPIVlzthA
LwUFcijKuWqfwDWGWAUv8poS3r6Ok1ZRpKrqn9TjrkYz3460m+1hHMiLsqjBVDRjKSXKSGi1
6Ss6uy65pds62ti2Kx+aHfFqg6WfKrp3bio5X5aFLTcMbM+zoih4mvM8T7wiwdU4cUgMxrSO
CAkejUJp9eR8GjnO4glmV1F066CQefcgPYvdOqmgsgphtlK9h7YgkYFAjQlMyoR0gxy6TkvF
M5bzUTnBoe3ix2C904OiPGDwK47P2N6IDKblXuC9sO5cg998lWh67mN6ddPF8d8jlGCcMu5P
6rs7ef/n/i7P/xnir7R2RGxAzqNn+pDntPIfVUevUEsHCLT3aNIFAQAAgwMAAFBLAwQUAAgI
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
qj3ilyQOPhr0ABLtL3rhZyov0EILLbTQQgsttND+W1rqv9n/cfyPtLu9/1v//Op6vYEY/1mt
W6p3rm9s+rFGaz8x2MF6O6wN/SU0Y2o3tvDifH1Jv4qU7vqardljWAZb3pyj1Tq6spysn/fd
2kTWub1a2+VJvKrVtXjeoiYdYprGsV9fxoqz3RtNUinHrl0haYvWpK6ELiWP4mOcD1bNUlgn
6uNKr69UXetjCoGnpsaut8D1spZC5LSaHJ0d1czXz8RDc7d5Xl9JkXeLGk6noLyv069jXdNk
vHUxiHZKk/clm/mSVvMxB7N+Wwrb+ur8Rl5vV7WKquUlh2kYw5Hzcn1uJ5KV344XmvjGZUpE
Stoq+wVtm/1QsoBjNO341mdqLcsKuza3xemjv4aNbm0aIxcZr6vahaTTlXfDKXC0/hPnbbIh
dLuFtK3JJRedK9LWwkv4dazpvPpsU+lmWzg6OQPk79IYL24UG9bslrl36/rubP6q+62s5Pf9
wHc1PnlNpg9l0CfL+PFzjx2XGxkfGnh7uNz5iO/djLTU957HpfBBL+pD0eqTRd9D7o/6e7y+
FvihAf0zWF0OlqCfvepL4Vohc/xLuiQb8JEHU5ZKK8zje+XvT6sPycePmnz4Ht4L/c7BjvxQ
okqyG1PpV7RJyfVaJ3XoNLfogiEllSAVaYLorhsnctwrZOQlenur3985r7+vxDrOVa7h5t79
g2aV7QOJ5jA3Zp3MfkE78spr5nXxXL0erGVDloocPvFtUd4Zmr3e9SJbgfZzf8nBurVNy3Qo
ye30uaENTd1KTi2JhPxyNutjV2NFaXsgTNKB5lK9tJLLyr5x1OeWrIjnTVJcK7mhyCW72Fil
RVKxeefJNrbtTDT4diYsRe0z70dtfGYwi2RAEm5b7UfOj82tm6eHlvLEeapzuaI957ZIJuBl
gM4pTefcynGfv+dXGCXispx2WSvuXdu8BEn6K6f8lk5tdzJYkhnObZP1/Nj3xHPwzGNa+Sog
s/Zr7b7Z3nVVh6qmhiXLeVvlkNdkzlZiYLWrbqpApuj7RLfd5Dy/acdUJWViard6qGJL9HmW
JnV9bG7H1LflgTDpfshB1wvavEn22sPOR5AlmSP9rHDmvp8P8kI+nxX5WC2UIh2V25Hlo+fZ
MrZt2+/VEs/L1vHg3PIeHhmmXbofb0eC/RZaaKGFFlpooYUWWmihhRZaaKGFFlpooYUWWmih
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
--------------4B194FF8F3EA3786FF9EAE1F
Content-Type: application/x-compressed-tar;
 name="brin-stress-test.tgz"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
 filename="brin-stress-test.tgz"

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
4sSJE/vk/y10LU4AkAEA
--------------4B194FF8F3EA3786FF9EAE1F
Content-Type: application/x-compressed-tar;
 name="brin-bench.tgz"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
 filename="brin-bench.tgz"

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
--------------4B194FF8F3EA3786FF9EAE1F--





^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/9] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 4e0c9be58c..4099e72001 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8191,7 +8191,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------0E72B707603BED22B4040825--





^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/9] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 1487710d59..33841e14f2 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8191,7 +8191,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------22A4B241170149838D4D1F8F
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210215.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210215.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 58fe109d2d..8a1a9da78f 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -389,6 +389,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -410,6 +413,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -470,7 +528,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -480,51 +538,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index d7b55f57ea..871e024e00 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8143,7 +8143,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8159,7 +8159,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------CF71AF65F7C337C37C24B045
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210112.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210112.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/6] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 58fe109d2d..8a1a9da78f 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -389,6 +389,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -410,6 +413,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -470,7 +528,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -480,51 +538,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index d7b55f57ea..871e024e00 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8143,7 +8143,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8159,7 +8159,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------D21F32E0F9E7408E9BE1AF2E
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210114.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210114.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/6] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index d27336adcd..f3ead7d53d 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8145,7 +8145,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8161,7 +8161,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------310A2AE1CC4C2E2E77559E3D
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-suppo-20210114-2.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-suppo-20210114-2.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index b5f52d4e4a..2ef11245a8 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8183,7 +8183,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8199,7 +8199,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------FA974B75A0C3E9CA18CE7207
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210122.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210122.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/6] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 158 ++++++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 140 ++++++++++++++------
 src/backend/access/brin/brin_minmax.c    |  92 ++++++++++---
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 303 insertions(+), 95 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..963b7079cf 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,78 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of
+					 * multiple scan keys. We can determine that based on the
+					 * number of arguments - functions with extra parameter
+					 * (number of scan keys) do support this, otherwise we
+					 * have to simply pass the scan keys one by one, as
+					 * before.
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same
+						 * for all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet
+						 * the criteria for a single one of them is enough to
+						 * discard the range as a whole, so break out of the
+						 * loop as soon as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+
+							/* mismatching key, no need to look further  */
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..a260074c91 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -251,6 +253,10 @@ brin_inclusion_add_value(PG_FUNCTION_ARGS)
 /*
  * BRIN inclusion consistent function
  *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
+ *
  * All of the strategies are optional.
  */
 Datum
@@ -258,24 +264,31 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/* Handle IS NULL/IS NOT NULL tests */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -284,7 +297,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -293,7 +311,14 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
@@ -301,10 +326,45 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all regular scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* Skip IS NULL/IS NOT NULL keys (already handled above). */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
+	/* This should be called only for regular keys, not for IS [NOT] NULL. */
+	Assert(!(key->sk_flags & SK_ISNULL));
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +384,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +444,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +464,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +483,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +518,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +528,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..e116084a02 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -140,29 +142,41 @@ brin_minmax_add_value(PG_FUNCTION_ARGS)
  * Given an index tuple corresponding to a certain page range and a scan key,
  * return whether the scan key is consistent with the index tuple's min/max
  * values.  Return true if so, false otherwise.
+ *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
  */
 Datum
 brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
 	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -171,7 +185,12 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -180,13 +199,52 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
+	}
+
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
+
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +287,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 1487710d59..33841e14f2 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8191,7 +8191,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------6A37408A2C42B5B56C3B3D49
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210303.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210303.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c          | 158 +++++++++++++++++++-----
 src/backend/access/brin/brin_validate.c |   4 +-
 2 files changed, 126 insertions(+), 36 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..963b7079cf 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,78 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of
+					 * multiple scan keys. We can determine that based on the
+					 * number of arguments - functions with extra parameter
+					 * (number of scan keys) do support this, otherwise we
+					 * have to simply pass the scan keys one by one, as
+					 * before.
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same
+						 * for all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet
+						 * the criteria for a single one of them is enough to
+						 * discard the range as a whole, so break out of the
+						 * loop as soon as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+
+							/* mismatching key, no need to look further  */
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-- 
2.26.2


--------------AC3FFB734F56C5F52D422EFC
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Process-all-scan-keys-in-existing-BRIN-opcl-20210305.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Process-all-scan-keys-in-existing-BRIN-opcl-20210305.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c          | 158 +++++++++++++++++++-----
 src/backend/access/brin/brin_validate.c |   4 +-
 2 files changed, 126 insertions(+), 36 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..f9a0476024 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,78 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any scan keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of
+					 * multiple scan keys. We can determine that based on the
+					 * number of arguments - functions with extra parameter
+					 * (number of scan keys) do support this, otherwise we
+					 * have to simply pass the scan keys one by one, as
+					 * before.
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same
+						 * for all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet
+						 * the criteria for a single one of them is enough to
+						 * discard the range as a whole, so break out of the
+						 * loop as soon as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+
+							/* mismatching key, no need to look further  */
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-- 
2.26.2


--------------82D677E9F94AC7574E460205
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Process-all-scan-keys-in-existing-BRIN-opcl-20210308.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Process-all-scan-keys-in-existing-BRIN-opcl-20210308.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c          | 158 +++++++++++++++++++-----
 src/backend/access/brin/brin_validate.c |   4 +-
 2 files changed, 126 insertions(+), 36 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..f9a0476024 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,78 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any scan keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of
+					 * multiple scan keys. We can determine that based on the
+					 * number of arguments - functions with extra parameter
+					 * (number of scan keys) do support this, otherwise we
+					 * have to simply pass the scan keys one by one, as
+					 * before.
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same
+						 * for all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet
+						 * the criteria for a single one of them is enough to
+						 * discard the range as a whole, so break out of the
+						 * loop as soon as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+
+							/* mismatching key, no need to look further  */
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-- 
2.26.2


--------------556A1DC61262AF15641DB204
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Process-all-scan-keys-in-existing-BRIN-opc-20210308b.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Process-all-scan-keys-in-existing-BRIN-opc-20210308b.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow future opclases to benefit from seeing all keys at once.

This does break existing BRIN opclasses, because the signature of the
consistent function changed. We might support both variants (with 3 and
4 parameters), but that seems pointless - the changes to NULL handling
likely require updates too. So better to make the failure clear. Also,
we're not aware of any out-of-core opclasses - there may be some, but
probably not many.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 doc/src/sgml/brin.sgml                   |   8 +-
 src/backend/access/brin/brin.c           | 118 +++++++++++++------
 src/backend/access/brin/brin_inclusion.c | 140 ++++++++++++++++-------
 src/backend/access/brin/brin_minmax.c    |  92 ++++++++++++---
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 6 files changed, 269 insertions(+), 97 deletions(-)

diff --git a/doc/src/sgml/brin.sgml b/doc/src/sgml/brin.sgml
index 06880c0f7b..078f51bb55 100644
--- a/doc/src/sgml/brin.sgml
+++ b/doc/src/sgml/brin.sgml
@@ -464,12 +464,14 @@ typedef struct BrinOpcInfo
 
    <varlistentry>
     <term><function>bool consistent(BrinDesc *bdesc, BrinValues *column,
-       ScanKey key)</function></term>
+       ScanKey *keys, int nkeys)</function></term>
     <listitem>
      <para>
-      Returns whether the ScanKey is consistent with the given indexed
-      values for a range.
+      Returns whether all the ScanKey entries are consistent with the given
+      indexed values for a range.
       The attribute number to use is passed as part of the scan key.
+      Multiple scan keys for the same attribute may be passed at once, the
+      number of entries is determined by the <literal>nkeys</literal> parameter.
      </para>
     </listitem>
    </varlistentry>
diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..743f2a925a 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,40 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
+					Oid			collation;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
-
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
-
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					/* skip attributes without any scan keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
+
+					bval = &dtup->bt_columns[attno - 1];
+
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * XXX We simply use the collation from the first key (it
+					 * has to be the same for all keys for the same attribue).
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
+					collation = keys[attno - 1][0]->sk_collation;
+
+					/* Check all keys at once */
+					add = FunctionCall4Coll(&consistentFn[attno - 1],
+											collation,
 											PointerGetDatum(bdesc),
 											PointerGetDatum(bval),
-											PointerGetDatum(key));
+											PointerGetDatum(keys[attno - 1]),
+											Int32GetDatum(nkeys[attno - 1]));
 					addrange = DatumGetBool(add);
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..a260074c91 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -251,6 +253,10 @@ brin_inclusion_add_value(PG_FUNCTION_ARGS)
 /*
  * BRIN inclusion consistent function
  *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
+ *
  * All of the strategies are optional.
  */
 Datum
@@ -258,24 +264,31 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/* Handle IS NULL/IS NOT NULL tests */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -284,7 +297,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -293,7 +311,14 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
@@ -301,10 +326,45 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all regular scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* Skip IS NULL/IS NOT NULL keys (already handled above). */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
+	/* This should be called only for regular keys, not for IS [NOT] NULL. */
+	Assert(!(key->sk_flags & SK_ISNULL));
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +384,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +444,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +464,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +483,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +518,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +528,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..e116084a02 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -140,29 +142,41 @@ brin_minmax_add_value(PG_FUNCTION_ARGS)
  * Given an index tuple corresponding to a certain page range and a scan key,
  * return whether the scan key is consistent with the index tuple's min/max
  * values.  Return true if so, false otherwise.
+ *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
  */
 Datum
 brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
 	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -171,7 +185,12 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -180,13 +199,52 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
+	}
+
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
+
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +287,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..2c4f9a3eff 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											4, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index c7619f8cd3..cd1eda38ab 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8223,7 +8223,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------D524CD37E77B36A2883A7617
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Move-IS-NOT-NULL-handling-from-BRIN-support-20210311.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Move-IS-NOT-NULL-handling-from-BRIN-support-20210311.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/9] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 4e0c9be58c..4099e72001 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8191,7 +8191,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------4B194FF8F3EA3786FF9EAE1F
Content-Type: application/vnd.oasis.opendocument.spreadsheet;
 name="brin-bench.ods"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
 filename="brin-bench.ods"

UEsDBBQAAAgAAOO7Q1KFbDmKLgAAAC4AAAAIAAAAbWltZXR5cGVhcHBsaWNhdGlvbi92bmQu
b2FzaXMub3BlbmRvY3VtZW50LnNwcmVhZHNoZWV0UEsDBBQAAAgAAOO7Q1IAAAAAAAAAAAAA
AAAcAAAAQ29uZmlndXJhdGlvbnMyL2FjY2VsZXJhdG9yL1BLAwQUAAAIAADju0NSAAAAAAAA
AAAAAAAAHwAAAENvbmZpZ3VyYXRpb25zMi9pbWFnZXMvQml0bWFwcy9QSwMEFAAACAAA47tD
UgAAAAAAAAAAAAAAABgAAABDb25maWd1cmF0aW9uczIvdG9vbGJhci9QSwMEFAAACAAA47tD
UgAAAAAAAAAAAAAAABgAAABDb25maWd1cmF0aW9uczIvZmxvYXRlci9QSwMEFAAACAAA47tD
UgAAAAAAAAAAAAAAABoAAABDb25maWd1cmF0aW9uczIvcG9wdXBtZW51L1BLAwQUAAAIAADj
u0NSAAAAAAAAAAAAAAAAGAAAAENvbmZpZ3VyYXRpb25zMi9tZW51YmFyL1BLAwQUAAAIAADj
u0NSAAAAAAAAAAAAAAAAGgAAAENvbmZpZ3VyYXRpb25zMi90b29scGFuZWwvUEsDBBQAAAgA
AOO7Q1IAAAAAAAAAAAAAAAAaAAAAQ29uZmlndXJhdGlvbnMyL3N0YXR1c2Jhci9QSwMEFAAA
CAAA47tDUgAAAAAAAAAAAAAAABwAAABDb25maWd1cmF0aW9uczIvcHJvZ3Jlc3NiYXIvUEsD
BBQACAgIAOO7Q1IAAAAAAAAAAAAAAAAMAAAAbWFuaWZlc3QucmRmzZPNboMwEITvPIVlzthA
LwUFcijKuWqfwDWGWAUv8poS3r6Ok1ZRpKrqn9TjrkYz3460m+1hHMiLsqjBVDRjKSXKSGi1
6Ss6uy65pds62ti2Kx+aHfFqg6WfKrp3bio5X5aFLTcMbM+zoih4mvM8T7wiwdU4cUgMxrSO
CAkejUJp9eR8GjnO4glmV1F066CQefcgPYvdOqmgsgphtlK9h7YgkYFAjQlMyoR0gxy6TkvF
M5bzUTnBoe3ix2C904OiPGDwK47P2N6IDKblXuC9sO5cg998lWh67mN6ddPF8d8jlGCcMu5P
6rs7ef/n/i7P/xnir7R2RGxAzqNn+pDntPIfVUevUEsHCLT3aNIFAQAAgwMAAFBLAwQUAAgI
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
qj3ilyQOPhr0ABLtL3rhZyov0EILLbTQQgsttND+W1rqv9n/cfyPtLu9/1v//Op6vYEY/1mt
W6p3rm9s+rFGaz8x2MF6O6wN/SU0Y2o3tvDifH1Jv4qU7vqardljWAZb3pyj1Tq6spysn/fd
2kTWub1a2+VJvKrVtXjeoiYdYprGsV9fxoqz3RtNUinHrl0haYvWpK6ELiWP4mOcD1bNUlgn
6uNKr69UXetjCoGnpsaut8D1spZC5LSaHJ0d1czXz8RDc7d5Xl9JkXeLGk6noLyv069jXdNk
vHUxiHZKk/clm/mSVvMxB7N+Wwrb+ur8Rl5vV7WKquUlh2kYw5Hzcn1uJ5KV344XmvjGZUpE
Stoq+wVtm/1QsoBjNO341mdqLcsKuza3xemjv4aNbm0aIxcZr6vahaTTlXfDKXC0/hPnbbIh
dLuFtK3JJRedK9LWwkv4dazpvPpsU+lmWzg6OQPk79IYL24UG9bslrl36/rubP6q+62s5Pf9
wHc1PnlNpg9l0CfL+PFzjx2XGxkfGnh7uNz5iO/djLTU957HpfBBL+pD0eqTRd9D7o/6e7y+
FvihAf0zWF0OlqCfvepL4Vohc/xLuiQb8JEHU5ZKK8zje+XvT6sPycePmnz4Ht4L/c7BjvxQ
okqyG1PpV7RJyfVaJ3XoNLfogiEllSAVaYLorhsnctwrZOQlenur3985r7+vxDrOVa7h5t79
g2aV7QOJ5jA3Zp3MfkE78spr5nXxXL0erGVDloocPvFtUd4Zmr3e9SJbgfZzf8nBurVNy3Qo
ye30uaENTd1KTi2JhPxyNutjV2NFaXsgTNKB5lK9tJLLyr5x1OeWrIjnTVJcK7mhyCW72Fil
RVKxeefJNrbtTDT4diYsRe0z70dtfGYwi2RAEm5b7UfOj82tm6eHlvLEeapzuaI957ZIJuBl
gM4pTefcynGfv+dXGCXispx2WSvuXdu8BEn6K6f8lk5tdzJYkhnObZP1/Nj3xHPwzGNa+Sog
s/Zr7b7Z3nVVh6qmhiXLeVvlkNdkzlZiYLWrbqpApuj7RLfd5Dy/acdUJWViard6qGJL9HmW
JnV9bG7H1LflgTDpfshB1wvavEn22sPOR5AlmSP9rHDmvp8P8kI+nxX5WC2UIh2V25Hlo+fZ
MrZt2+/VEs/L1vHg3PIeHhmmXbofb0eC/RZaaKGFFlpooYUWWmihhRZaaKGFFlpooYUWWmih
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
--------------4B194FF8F3EA3786FF9EAE1F
Content-Type: application/x-compressed-tar;
 name="brin-stress-test.tgz"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
 filename="brin-stress-test.tgz"

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
4sSJE/vk/y10LU4AkAEA
--------------4B194FF8F3EA3786FF9EAE1F
Content-Type: application/x-compressed-tar;
 name="brin-bench.tgz"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
 filename="brin-bench.tgz"

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
--------------4B194FF8F3EA3786FF9EAE1F--





^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/9] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 4e0c9be58c..4099e72001 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8191,7 +8191,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------0E72B707603BED22B4040825--





^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/9] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 1487710d59..33841e14f2 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8191,7 +8191,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------22A4B241170149838D4D1F8F
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210215.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210215.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 58fe109d2d..8a1a9da78f 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -389,6 +389,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -410,6 +413,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -470,7 +528,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -480,51 +538,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index d7b55f57ea..871e024e00 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8143,7 +8143,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8159,7 +8159,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------CF71AF65F7C337C37C24B045
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210112.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210112.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/6] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 58fe109d2d..8a1a9da78f 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -389,6 +389,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -410,6 +413,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -470,7 +528,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -480,51 +538,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index d7b55f57ea..871e024e00 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8143,7 +8143,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8159,7 +8159,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------D21F32E0F9E7408E9BE1AF2E
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210114.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210114.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/6] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index d27336adcd..f3ead7d53d 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8145,7 +8145,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8161,7 +8161,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------310A2AE1CC4C2E2E77559E3D
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-suppo-20210114-2.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-suppo-20210114-2.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index b5f52d4e4a..2ef11245a8 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8183,7 +8183,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8199,7 +8199,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------FA974B75A0C3E9CA18CE7207
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210122.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210122.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/6] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 158 ++++++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 140 ++++++++++++++------
 src/backend/access/brin/brin_minmax.c    |  92 ++++++++++---
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 303 insertions(+), 95 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..963b7079cf 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,78 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of
+					 * multiple scan keys. We can determine that based on the
+					 * number of arguments - functions with extra parameter
+					 * (number of scan keys) do support this, otherwise we
+					 * have to simply pass the scan keys one by one, as
+					 * before.
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same
+						 * for all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet
+						 * the criteria for a single one of them is enough to
+						 * discard the range as a whole, so break out of the
+						 * loop as soon as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+
+							/* mismatching key, no need to look further  */
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..a260074c91 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -251,6 +253,10 @@ brin_inclusion_add_value(PG_FUNCTION_ARGS)
 /*
  * BRIN inclusion consistent function
  *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
+ *
  * All of the strategies are optional.
  */
 Datum
@@ -258,24 +264,31 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/* Handle IS NULL/IS NOT NULL tests */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -284,7 +297,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -293,7 +311,14 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
@@ -301,10 +326,45 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all regular scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* Skip IS NULL/IS NOT NULL keys (already handled above). */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
+	/* This should be called only for regular keys, not for IS [NOT] NULL. */
+	Assert(!(key->sk_flags & SK_ISNULL));
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +384,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +444,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +464,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +483,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +518,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +528,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..e116084a02 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -140,29 +142,41 @@ brin_minmax_add_value(PG_FUNCTION_ARGS)
  * Given an index tuple corresponding to a certain page range and a scan key,
  * return whether the scan key is consistent with the index tuple's min/max
  * values.  Return true if so, false otherwise.
+ *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
  */
 Datum
 brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
 	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -171,7 +185,12 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -180,13 +199,52 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
+	}
+
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
+
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +287,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 1487710d59..33841e14f2 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8191,7 +8191,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------6A37408A2C42B5B56C3B3D49
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210303.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210303.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c          | 158 +++++++++++++++++++-----
 src/backend/access/brin/brin_validate.c |   4 +-
 2 files changed, 126 insertions(+), 36 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..963b7079cf 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,78 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of
+					 * multiple scan keys. We can determine that based on the
+					 * number of arguments - functions with extra parameter
+					 * (number of scan keys) do support this, otherwise we
+					 * have to simply pass the scan keys one by one, as
+					 * before.
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same
+						 * for all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet
+						 * the criteria for a single one of them is enough to
+						 * discard the range as a whole, so break out of the
+						 * loop as soon as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+
+							/* mismatching key, no need to look further  */
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-- 
2.26.2


--------------AC3FFB734F56C5F52D422EFC
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Process-all-scan-keys-in-existing-BRIN-opcl-20210305.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Process-all-scan-keys-in-existing-BRIN-opcl-20210305.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c          | 158 +++++++++++++++++++-----
 src/backend/access/brin/brin_validate.c |   4 +-
 2 files changed, 126 insertions(+), 36 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..f9a0476024 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,78 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any scan keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of
+					 * multiple scan keys. We can determine that based on the
+					 * number of arguments - functions with extra parameter
+					 * (number of scan keys) do support this, otherwise we
+					 * have to simply pass the scan keys one by one, as
+					 * before.
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same
+						 * for all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet
+						 * the criteria for a single one of them is enough to
+						 * discard the range as a whole, so break out of the
+						 * loop as soon as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+
+							/* mismatching key, no need to look further  */
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-- 
2.26.2


--------------82D677E9F94AC7574E460205
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Process-all-scan-keys-in-existing-BRIN-opcl-20210308.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Process-all-scan-keys-in-existing-BRIN-opcl-20210308.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c          | 158 +++++++++++++++++++-----
 src/backend/access/brin/brin_validate.c |   4 +-
 2 files changed, 126 insertions(+), 36 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..f9a0476024 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,78 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any scan keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of
+					 * multiple scan keys. We can determine that based on the
+					 * number of arguments - functions with extra parameter
+					 * (number of scan keys) do support this, otherwise we
+					 * have to simply pass the scan keys one by one, as
+					 * before.
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same
+						 * for all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet
+						 * the criteria for a single one of them is enough to
+						 * discard the range as a whole, so break out of the
+						 * loop as soon as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+
+							/* mismatching key, no need to look further  */
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-- 
2.26.2


--------------556A1DC61262AF15641DB204
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Process-all-scan-keys-in-existing-BRIN-opc-20210308b.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Process-all-scan-keys-in-existing-BRIN-opc-20210308b.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow future opclases to benefit from seeing all keys at once.

This does break existing BRIN opclasses, because the signature of the
consistent function changed. We might support both variants (with 3 and
4 parameters), but that seems pointless - the changes to NULL handling
likely require updates too. So better to make the failure clear. Also,
we're not aware of any out-of-core opclasses - there may be some, but
probably not many.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 doc/src/sgml/brin.sgml                   |   8 +-
 src/backend/access/brin/brin.c           | 118 +++++++++++++------
 src/backend/access/brin/brin_inclusion.c | 140 ++++++++++++++++-------
 src/backend/access/brin/brin_minmax.c    |  92 ++++++++++++---
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 6 files changed, 269 insertions(+), 97 deletions(-)

diff --git a/doc/src/sgml/brin.sgml b/doc/src/sgml/brin.sgml
index 06880c0f7b..078f51bb55 100644
--- a/doc/src/sgml/brin.sgml
+++ b/doc/src/sgml/brin.sgml
@@ -464,12 +464,14 @@ typedef struct BrinOpcInfo
 
    <varlistentry>
     <term><function>bool consistent(BrinDesc *bdesc, BrinValues *column,
-       ScanKey key)</function></term>
+       ScanKey *keys, int nkeys)</function></term>
     <listitem>
      <para>
-      Returns whether the ScanKey is consistent with the given indexed
-      values for a range.
+      Returns whether all the ScanKey entries are consistent with the given
+      indexed values for a range.
       The attribute number to use is passed as part of the scan key.
+      Multiple scan keys for the same attribute may be passed at once, the
+      number of entries is determined by the <literal>nkeys</literal> parameter.
      </para>
     </listitem>
    </varlistentry>
diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..743f2a925a 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,40 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
+					Oid			collation;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
-
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
-
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					/* skip attributes without any scan keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
+
+					bval = &dtup->bt_columns[attno - 1];
+
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * XXX We simply use the collation from the first key (it
+					 * has to be the same for all keys for the same attribue).
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
+					collation = keys[attno - 1][0]->sk_collation;
+
+					/* Check all keys at once */
+					add = FunctionCall4Coll(&consistentFn[attno - 1],
+											collation,
 											PointerGetDatum(bdesc),
 											PointerGetDatum(bval),
-											PointerGetDatum(key));
+											PointerGetDatum(keys[attno - 1]),
+											Int32GetDatum(nkeys[attno - 1]));
 					addrange = DatumGetBool(add);
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..a260074c91 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -251,6 +253,10 @@ brin_inclusion_add_value(PG_FUNCTION_ARGS)
 /*
  * BRIN inclusion consistent function
  *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
+ *
  * All of the strategies are optional.
  */
 Datum
@@ -258,24 +264,31 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/* Handle IS NULL/IS NOT NULL tests */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -284,7 +297,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -293,7 +311,14 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
@@ -301,10 +326,45 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all regular scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* Skip IS NULL/IS NOT NULL keys (already handled above). */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
+	/* This should be called only for regular keys, not for IS [NOT] NULL. */
+	Assert(!(key->sk_flags & SK_ISNULL));
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +384,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +444,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +464,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +483,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +518,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +528,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..e116084a02 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -140,29 +142,41 @@ brin_minmax_add_value(PG_FUNCTION_ARGS)
  * Given an index tuple corresponding to a certain page range and a scan key,
  * return whether the scan key is consistent with the index tuple's min/max
  * values.  Return true if so, false otherwise.
+ *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
  */
 Datum
 brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
 	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -171,7 +185,12 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -180,13 +199,52 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
+	}
+
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
+
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +287,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..2c4f9a3eff 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											4, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index c7619f8cd3..cd1eda38ab 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8223,7 +8223,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------D524CD37E77B36A2883A7617
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Move-IS-NOT-NULL-handling-from-BRIN-support-20210311.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Move-IS-NOT-NULL-handling-from-BRIN-support-20210311.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/9] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 4e0c9be58c..4099e72001 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8191,7 +8191,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------4B194FF8F3EA3786FF9EAE1F
Content-Type: application/vnd.oasis.opendocument.spreadsheet;
 name="brin-bench.ods"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
 filename="brin-bench.ods"

UEsDBBQAAAgAAOO7Q1KFbDmKLgAAAC4AAAAIAAAAbWltZXR5cGVhcHBsaWNhdGlvbi92bmQu
b2FzaXMub3BlbmRvY3VtZW50LnNwcmVhZHNoZWV0UEsDBBQAAAgAAOO7Q1IAAAAAAAAAAAAA
AAAcAAAAQ29uZmlndXJhdGlvbnMyL2FjY2VsZXJhdG9yL1BLAwQUAAAIAADju0NSAAAAAAAA
AAAAAAAAHwAAAENvbmZpZ3VyYXRpb25zMi9pbWFnZXMvQml0bWFwcy9QSwMEFAAACAAA47tD
UgAAAAAAAAAAAAAAABgAAABDb25maWd1cmF0aW9uczIvdG9vbGJhci9QSwMEFAAACAAA47tD
UgAAAAAAAAAAAAAAABgAAABDb25maWd1cmF0aW9uczIvZmxvYXRlci9QSwMEFAAACAAA47tD
UgAAAAAAAAAAAAAAABoAAABDb25maWd1cmF0aW9uczIvcG9wdXBtZW51L1BLAwQUAAAIAADj
u0NSAAAAAAAAAAAAAAAAGAAAAENvbmZpZ3VyYXRpb25zMi9tZW51YmFyL1BLAwQUAAAIAADj
u0NSAAAAAAAAAAAAAAAAGgAAAENvbmZpZ3VyYXRpb25zMi90b29scGFuZWwvUEsDBBQAAAgA
AOO7Q1IAAAAAAAAAAAAAAAAaAAAAQ29uZmlndXJhdGlvbnMyL3N0YXR1c2Jhci9QSwMEFAAA
CAAA47tDUgAAAAAAAAAAAAAAABwAAABDb25maWd1cmF0aW9uczIvcHJvZ3Jlc3NiYXIvUEsD
BBQACAgIAOO7Q1IAAAAAAAAAAAAAAAAMAAAAbWFuaWZlc3QucmRmzZPNboMwEITvPIVlzthA
LwUFcijKuWqfwDWGWAUv8poS3r6Ok1ZRpKrqn9TjrkYz3460m+1hHMiLsqjBVDRjKSXKSGi1
6Ss6uy65pds62ti2Kx+aHfFqg6WfKrp3bio5X5aFLTcMbM+zoih4mvM8T7wiwdU4cUgMxrSO
CAkejUJp9eR8GjnO4glmV1F066CQefcgPYvdOqmgsgphtlK9h7YgkYFAjQlMyoR0gxy6TkvF
M5bzUTnBoe3ix2C904OiPGDwK47P2N6IDKblXuC9sO5cg998lWh67mN6ddPF8d8jlGCcMu5P
6rs7ef/n/i7P/xnir7R2RGxAzqNn+pDntPIfVUevUEsHCLT3aNIFAQAAgwMAAFBLAwQUAAgI
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
qj3ilyQOPhr0ABLtL3rhZyov0EILLbTQQgsttND+W1rqv9n/cfyPtLu9/1v//Op6vYEY/1mt
W6p3rm9s+rFGaz8x2MF6O6wN/SU0Y2o3tvDifH1Jv4qU7vqardljWAZb3pyj1Tq6spysn/fd
2kTWub1a2+VJvKrVtXjeoiYdYprGsV9fxoqz3RtNUinHrl0haYvWpK6ELiWP4mOcD1bNUlgn
6uNKr69UXetjCoGnpsaut8D1spZC5LSaHJ0d1czXz8RDc7d5Xl9JkXeLGk6noLyv069jXdNk
vHUxiHZKk/clm/mSVvMxB7N+Wwrb+ur8Rl5vV7WKquUlh2kYw5Hzcn1uJ5KV344XmvjGZUpE
Stoq+wVtm/1QsoBjNO341mdqLcsKuza3xemjv4aNbm0aIxcZr6vahaTTlXfDKXC0/hPnbbIh
dLuFtK3JJRedK9LWwkv4dazpvPpsU+lmWzg6OQPk79IYL24UG9bslrl36/rubP6q+62s5Pf9
wHc1PnlNpg9l0CfL+PFzjx2XGxkfGnh7uNz5iO/djLTU957HpfBBL+pD0eqTRd9D7o/6e7y+
FvihAf0zWF0OlqCfvepL4Vohc/xLuiQb8JEHU5ZKK8zje+XvT6sPycePmnz4Ht4L/c7BjvxQ
okqyG1PpV7RJyfVaJ3XoNLfogiEllSAVaYLorhsnctwrZOQlenur3985r7+vxDrOVa7h5t79
g2aV7QOJ5jA3Zp3MfkE78spr5nXxXL0erGVDloocPvFtUd4Zmr3e9SJbgfZzf8nBurVNy3Qo
ye30uaENTd1KTi2JhPxyNutjV2NFaXsgTNKB5lK9tJLLyr5x1OeWrIjnTVJcK7mhyCW72Fil
RVKxeefJNrbtTDT4diYsRe0z70dtfGYwi2RAEm5b7UfOj82tm6eHlvLEeapzuaI957ZIJuBl
gM4pTefcynGfv+dXGCXispx2WSvuXdu8BEn6K6f8lk5tdzJYkhnObZP1/Nj3xHPwzGNa+Sog
s/Zr7b7Z3nVVh6qmhiXLeVvlkNdkzlZiYLWrbqpApuj7RLfd5Dy/acdUJWViard6qGJL9HmW
JnV9bG7H1LflgTDpfshB1wvavEn22sPOR5AlmSP9rHDmvp8P8kI+nxX5WC2UIh2V25Hlo+fZ
MrZt2+/VEs/L1vHg3PIeHhmmXbofb0eC/RZaaKGFFlpooYUWWmihhRZaaKGFFlpooYUWWmih
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
--------------4B194FF8F3EA3786FF9EAE1F
Content-Type: application/x-compressed-tar;
 name="brin-stress-test.tgz"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
 filename="brin-stress-test.tgz"

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
4sSJE/vk/y10LU4AkAEA
--------------4B194FF8F3EA3786FF9EAE1F
Content-Type: application/x-compressed-tar;
 name="brin-bench.tgz"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
 filename="brin-bench.tgz"

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
--------------4B194FF8F3EA3786FF9EAE1F--





^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/9] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 4e0c9be58c..4099e72001 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8191,7 +8191,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------0E72B707603BED22B4040825--





^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/9] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 1487710d59..33841e14f2 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8191,7 +8191,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------22A4B241170149838D4D1F8F
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210215.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210215.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 58fe109d2d..8a1a9da78f 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -389,6 +389,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -410,6 +413,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -470,7 +528,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -480,51 +538,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index d7b55f57ea..871e024e00 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8143,7 +8143,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8159,7 +8159,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------CF71AF65F7C337C37C24B045
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210112.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210112.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/6] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 58fe109d2d..8a1a9da78f 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -389,6 +389,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -410,6 +413,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -470,7 +528,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -480,51 +538,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index d7b55f57ea..871e024e00 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8143,7 +8143,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8159,7 +8159,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------D21F32E0F9E7408E9BE1AF2E
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210114.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210114.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/6] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index d27336adcd..f3ead7d53d 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8145,7 +8145,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8161,7 +8161,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------310A2AE1CC4C2E2E77559E3D
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-suppo-20210114-2.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-suppo-20210114-2.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index b5f52d4e4a..2ef11245a8 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8183,7 +8183,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8199,7 +8199,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------FA974B75A0C3E9CA18CE7207
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210122.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210122.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/6] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 158 ++++++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 140 ++++++++++++++------
 src/backend/access/brin/brin_minmax.c    |  92 ++++++++++---
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 303 insertions(+), 95 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..963b7079cf 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,78 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of
+					 * multiple scan keys. We can determine that based on the
+					 * number of arguments - functions with extra parameter
+					 * (number of scan keys) do support this, otherwise we
+					 * have to simply pass the scan keys one by one, as
+					 * before.
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same
+						 * for all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet
+						 * the criteria for a single one of them is enough to
+						 * discard the range as a whole, so break out of the
+						 * loop as soon as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+
+							/* mismatching key, no need to look further  */
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..a260074c91 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -251,6 +253,10 @@ brin_inclusion_add_value(PG_FUNCTION_ARGS)
 /*
  * BRIN inclusion consistent function
  *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
+ *
  * All of the strategies are optional.
  */
 Datum
@@ -258,24 +264,31 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/* Handle IS NULL/IS NOT NULL tests */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -284,7 +297,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -293,7 +311,14 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
@@ -301,10 +326,45 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all regular scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* Skip IS NULL/IS NOT NULL keys (already handled above). */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
+	/* This should be called only for regular keys, not for IS [NOT] NULL. */
+	Assert(!(key->sk_flags & SK_ISNULL));
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +384,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +444,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +464,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +483,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +518,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +528,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..e116084a02 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -140,29 +142,41 @@ brin_minmax_add_value(PG_FUNCTION_ARGS)
  * Given an index tuple corresponding to a certain page range and a scan key,
  * return whether the scan key is consistent with the index tuple's min/max
  * values.  Return true if so, false otherwise.
+ *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
  */
 Datum
 brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
 	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -171,7 +185,12 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -180,13 +199,52 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
+	}
+
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
+
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +287,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 1487710d59..33841e14f2 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8191,7 +8191,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------6A37408A2C42B5B56C3B3D49
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210303.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210303.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c          | 158 +++++++++++++++++++-----
 src/backend/access/brin/brin_validate.c |   4 +-
 2 files changed, 126 insertions(+), 36 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..963b7079cf 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,78 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of
+					 * multiple scan keys. We can determine that based on the
+					 * number of arguments - functions with extra parameter
+					 * (number of scan keys) do support this, otherwise we
+					 * have to simply pass the scan keys one by one, as
+					 * before.
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same
+						 * for all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet
+						 * the criteria for a single one of them is enough to
+						 * discard the range as a whole, so break out of the
+						 * loop as soon as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+
+							/* mismatching key, no need to look further  */
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-- 
2.26.2


--------------AC3FFB734F56C5F52D422EFC
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Process-all-scan-keys-in-existing-BRIN-opcl-20210305.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Process-all-scan-keys-in-existing-BRIN-opcl-20210305.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c          | 158 +++++++++++++++++++-----
 src/backend/access/brin/brin_validate.c |   4 +-
 2 files changed, 126 insertions(+), 36 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..f9a0476024 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,78 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any scan keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of
+					 * multiple scan keys. We can determine that based on the
+					 * number of arguments - functions with extra parameter
+					 * (number of scan keys) do support this, otherwise we
+					 * have to simply pass the scan keys one by one, as
+					 * before.
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same
+						 * for all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet
+						 * the criteria for a single one of them is enough to
+						 * discard the range as a whole, so break out of the
+						 * loop as soon as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+
+							/* mismatching key, no need to look further  */
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-- 
2.26.2


--------------82D677E9F94AC7574E460205
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Process-all-scan-keys-in-existing-BRIN-opcl-20210308.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Process-all-scan-keys-in-existing-BRIN-opcl-20210308.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c          | 158 +++++++++++++++++++-----
 src/backend/access/brin/brin_validate.c |   4 +-
 2 files changed, 126 insertions(+), 36 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..f9a0476024 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,78 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any scan keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of
+					 * multiple scan keys. We can determine that based on the
+					 * number of arguments - functions with extra parameter
+					 * (number of scan keys) do support this, otherwise we
+					 * have to simply pass the scan keys one by one, as
+					 * before.
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same
+						 * for all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet
+						 * the criteria for a single one of them is enough to
+						 * discard the range as a whole, so break out of the
+						 * loop as soon as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+
+							/* mismatching key, no need to look further  */
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-- 
2.26.2


--------------556A1DC61262AF15641DB204
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Process-all-scan-keys-in-existing-BRIN-opc-20210308b.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Process-all-scan-keys-in-existing-BRIN-opc-20210308b.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow future opclases to benefit from seeing all keys at once.

This does break existing BRIN opclasses, because the signature of the
consistent function changed. We might support both variants (with 3 and
4 parameters), but that seems pointless - the changes to NULL handling
likely require updates too. So better to make the failure clear. Also,
we're not aware of any out-of-core opclasses - there may be some, but
probably not many.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 doc/src/sgml/brin.sgml                   |   8 +-
 src/backend/access/brin/brin.c           | 118 +++++++++++++------
 src/backend/access/brin/brin_inclusion.c | 140 ++++++++++++++++-------
 src/backend/access/brin/brin_minmax.c    |  92 ++++++++++++---
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 6 files changed, 269 insertions(+), 97 deletions(-)

diff --git a/doc/src/sgml/brin.sgml b/doc/src/sgml/brin.sgml
index 06880c0f7b..078f51bb55 100644
--- a/doc/src/sgml/brin.sgml
+++ b/doc/src/sgml/brin.sgml
@@ -464,12 +464,14 @@ typedef struct BrinOpcInfo
 
    <varlistentry>
     <term><function>bool consistent(BrinDesc *bdesc, BrinValues *column,
-       ScanKey key)</function></term>
+       ScanKey *keys, int nkeys)</function></term>
     <listitem>
      <para>
-      Returns whether the ScanKey is consistent with the given indexed
-      values for a range.
+      Returns whether all the ScanKey entries are consistent with the given
+      indexed values for a range.
       The attribute number to use is passed as part of the scan key.
+      Multiple scan keys for the same attribute may be passed at once, the
+      number of entries is determined by the <literal>nkeys</literal> parameter.
      </para>
     </listitem>
    </varlistentry>
diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..743f2a925a 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,40 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
+					Oid			collation;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
-
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
-
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					/* skip attributes without any scan keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
+
+					bval = &dtup->bt_columns[attno - 1];
+
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * XXX We simply use the collation from the first key (it
+					 * has to be the same for all keys for the same attribue).
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
+					collation = keys[attno - 1][0]->sk_collation;
+
+					/* Check all keys at once */
+					add = FunctionCall4Coll(&consistentFn[attno - 1],
+											collation,
 											PointerGetDatum(bdesc),
 											PointerGetDatum(bval),
-											PointerGetDatum(key));
+											PointerGetDatum(keys[attno - 1]),
+											Int32GetDatum(nkeys[attno - 1]));
 					addrange = DatumGetBool(add);
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..a260074c91 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -251,6 +253,10 @@ brin_inclusion_add_value(PG_FUNCTION_ARGS)
 /*
  * BRIN inclusion consistent function
  *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
+ *
  * All of the strategies are optional.
  */
 Datum
@@ -258,24 +264,31 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/* Handle IS NULL/IS NOT NULL tests */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -284,7 +297,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -293,7 +311,14 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
@@ -301,10 +326,45 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all regular scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* Skip IS NULL/IS NOT NULL keys (already handled above). */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
+	/* This should be called only for regular keys, not for IS [NOT] NULL. */
+	Assert(!(key->sk_flags & SK_ISNULL));
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +384,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +444,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +464,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +483,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +518,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +528,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..e116084a02 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -140,29 +142,41 @@ brin_minmax_add_value(PG_FUNCTION_ARGS)
  * Given an index tuple corresponding to a certain page range and a scan key,
  * return whether the scan key is consistent with the index tuple's min/max
  * values.  Return true if so, false otherwise.
+ *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
  */
 Datum
 brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
 	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -171,7 +185,12 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -180,13 +199,52 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
+	}
+
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
+
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +287,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..2c4f9a3eff 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											4, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index c7619f8cd3..cd1eda38ab 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8223,7 +8223,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------D524CD37E77B36A2883A7617
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Move-IS-NOT-NULL-handling-from-BRIN-support-20210311.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Move-IS-NOT-NULL-handling-from-BRIN-support-20210311.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/9] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 4e0c9be58c..4099e72001 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8191,7 +8191,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------4B194FF8F3EA3786FF9EAE1F
Content-Type: application/vnd.oasis.opendocument.spreadsheet;
 name="brin-bench.ods"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
 filename="brin-bench.ods"

UEsDBBQAAAgAAOO7Q1KFbDmKLgAAAC4AAAAIAAAAbWltZXR5cGVhcHBsaWNhdGlvbi92bmQu
b2FzaXMub3BlbmRvY3VtZW50LnNwcmVhZHNoZWV0UEsDBBQAAAgAAOO7Q1IAAAAAAAAAAAAA
AAAcAAAAQ29uZmlndXJhdGlvbnMyL2FjY2VsZXJhdG9yL1BLAwQUAAAIAADju0NSAAAAAAAA
AAAAAAAAHwAAAENvbmZpZ3VyYXRpb25zMi9pbWFnZXMvQml0bWFwcy9QSwMEFAAACAAA47tD
UgAAAAAAAAAAAAAAABgAAABDb25maWd1cmF0aW9uczIvdG9vbGJhci9QSwMEFAAACAAA47tD
UgAAAAAAAAAAAAAAABgAAABDb25maWd1cmF0aW9uczIvZmxvYXRlci9QSwMEFAAACAAA47tD
UgAAAAAAAAAAAAAAABoAAABDb25maWd1cmF0aW9uczIvcG9wdXBtZW51L1BLAwQUAAAIAADj
u0NSAAAAAAAAAAAAAAAAGAAAAENvbmZpZ3VyYXRpb25zMi9tZW51YmFyL1BLAwQUAAAIAADj
u0NSAAAAAAAAAAAAAAAAGgAAAENvbmZpZ3VyYXRpb25zMi90b29scGFuZWwvUEsDBBQAAAgA
AOO7Q1IAAAAAAAAAAAAAAAAaAAAAQ29uZmlndXJhdGlvbnMyL3N0YXR1c2Jhci9QSwMEFAAA
CAAA47tDUgAAAAAAAAAAAAAAABwAAABDb25maWd1cmF0aW9uczIvcHJvZ3Jlc3NiYXIvUEsD
BBQACAgIAOO7Q1IAAAAAAAAAAAAAAAAMAAAAbWFuaWZlc3QucmRmzZPNboMwEITvPIVlzthA
LwUFcijKuWqfwDWGWAUv8poS3r6Ok1ZRpKrqn9TjrkYz3460m+1hHMiLsqjBVDRjKSXKSGi1
6Ss6uy65pds62ti2Kx+aHfFqg6WfKrp3bio5X5aFLTcMbM+zoih4mvM8T7wiwdU4cUgMxrSO
CAkejUJp9eR8GjnO4glmV1F066CQefcgPYvdOqmgsgphtlK9h7YgkYFAjQlMyoR0gxy6TkvF
M5bzUTnBoe3ix2C904OiPGDwK47P2N6IDKblXuC9sO5cg998lWh67mN6ddPF8d8jlGCcMu5P
6rs7ef/n/i7P/xnir7R2RGxAzqNn+pDntPIfVUevUEsHCLT3aNIFAQAAgwMAAFBLAwQUAAgI
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
qj3ilyQOPhr0ABLtL3rhZyov0EILLbTQQgsttND+W1rqv9n/cfyPtLu9/1v//Op6vYEY/1mt
W6p3rm9s+rFGaz8x2MF6O6wN/SU0Y2o3tvDifH1Jv4qU7vqardljWAZb3pyj1Tq6spysn/fd
2kTWub1a2+VJvKrVtXjeoiYdYprGsV9fxoqz3RtNUinHrl0haYvWpK6ELiWP4mOcD1bNUlgn
6uNKr69UXetjCoGnpsaut8D1spZC5LSaHJ0d1czXz8RDc7d5Xl9JkXeLGk6noLyv069jXdNk
vHUxiHZKk/clm/mSVvMxB7N+Wwrb+ur8Rl5vV7WKquUlh2kYw5Hzcn1uJ5KV344XmvjGZUpE
Stoq+wVtm/1QsoBjNO341mdqLcsKuza3xemjv4aNbm0aIxcZr6vahaTTlXfDKXC0/hPnbbIh
dLuFtK3JJRedK9LWwkv4dazpvPpsU+lmWzg6OQPk79IYL24UG9bslrl36/rubP6q+62s5Pf9
wHc1PnlNpg9l0CfL+PFzjx2XGxkfGnh7uNz5iO/djLTU957HpfBBL+pD0eqTRd9D7o/6e7y+
FvihAf0zWF0OlqCfvepL4Vohc/xLuiQb8JEHU5ZKK8zje+XvT6sPycePmnz4Ht4L/c7BjvxQ
okqyG1PpV7RJyfVaJ3XoNLfogiEllSAVaYLorhsnctwrZOQlenur3985r7+vxDrOVa7h5t79
g2aV7QOJ5jA3Zp3MfkE78spr5nXxXL0erGVDloocPvFtUd4Zmr3e9SJbgfZzf8nBurVNy3Qo
ye30uaENTd1KTi2JhPxyNutjV2NFaXsgTNKB5lK9tJLLyr5x1OeWrIjnTVJcK7mhyCW72Fil
RVKxeefJNrbtTDT4diYsRe0z70dtfGYwi2RAEm5b7UfOj82tm6eHlvLEeapzuaI957ZIJuBl
gM4pTefcynGfv+dXGCXispx2WSvuXdu8BEn6K6f8lk5tdzJYkhnObZP1/Nj3xHPwzGNa+Sog
s/Zr7b7Z3nVVh6qmhiXLeVvlkNdkzlZiYLWrbqpApuj7RLfd5Dy/acdUJWViard6qGJL9HmW
JnV9bG7H1LflgTDpfshB1wvavEn22sPOR5AlmSP9rHDmvp8P8kI+nxX5WC2UIh2V25Hlo+fZ
MrZt2+/VEs/L1vHg3PIeHhmmXbofb0eC/RZaaKGFFlpooYUWWmihhRZaaKGFFlpooYUWWmih
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
--------------4B194FF8F3EA3786FF9EAE1F
Content-Type: application/x-compressed-tar;
 name="brin-stress-test.tgz"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
 filename="brin-stress-test.tgz"

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
4sSJE/vk/y10LU4AkAEA
--------------4B194FF8F3EA3786FF9EAE1F
Content-Type: application/x-compressed-tar;
 name="brin-bench.tgz"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
 filename="brin-bench.tgz"

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
--------------4B194FF8F3EA3786FF9EAE1F--





^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/9] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 4e0c9be58c..4099e72001 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8191,7 +8191,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------0E72B707603BED22B4040825--





^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/9] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 1487710d59..33841e14f2 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8191,7 +8191,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------22A4B241170149838D4D1F8F
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210215.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210215.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 58fe109d2d..8a1a9da78f 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -389,6 +389,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -410,6 +413,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -470,7 +528,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -480,51 +538,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index d7b55f57ea..871e024e00 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8143,7 +8143,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8159,7 +8159,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------CF71AF65F7C337C37C24B045
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210112.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210112.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/6] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 58fe109d2d..8a1a9da78f 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -389,6 +389,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -410,6 +413,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -470,7 +528,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -480,51 +538,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index d7b55f57ea..871e024e00 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8143,7 +8143,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8159,7 +8159,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------D21F32E0F9E7408E9BE1AF2E
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210114.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210114.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/6] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index d27336adcd..f3ead7d53d 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8145,7 +8145,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8161,7 +8161,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------310A2AE1CC4C2E2E77559E3D
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-suppo-20210114-2.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-suppo-20210114-2.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index b5f52d4e4a..2ef11245a8 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8183,7 +8183,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8199,7 +8199,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------FA974B75A0C3E9CA18CE7207
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210122.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210122.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/6] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 158 ++++++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 140 ++++++++++++++------
 src/backend/access/brin/brin_minmax.c    |  92 ++++++++++---
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 303 insertions(+), 95 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..963b7079cf 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,78 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of
+					 * multiple scan keys. We can determine that based on the
+					 * number of arguments - functions with extra parameter
+					 * (number of scan keys) do support this, otherwise we
+					 * have to simply pass the scan keys one by one, as
+					 * before.
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same
+						 * for all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet
+						 * the criteria for a single one of them is enough to
+						 * discard the range as a whole, so break out of the
+						 * loop as soon as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+
+							/* mismatching key, no need to look further  */
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..a260074c91 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -251,6 +253,10 @@ brin_inclusion_add_value(PG_FUNCTION_ARGS)
 /*
  * BRIN inclusion consistent function
  *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
+ *
  * All of the strategies are optional.
  */
 Datum
@@ -258,24 +264,31 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/* Handle IS NULL/IS NOT NULL tests */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -284,7 +297,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -293,7 +311,14 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
@@ -301,10 +326,45 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all regular scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* Skip IS NULL/IS NOT NULL keys (already handled above). */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
+	/* This should be called only for regular keys, not for IS [NOT] NULL. */
+	Assert(!(key->sk_flags & SK_ISNULL));
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +384,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +444,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +464,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +483,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +518,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +528,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..e116084a02 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -140,29 +142,41 @@ brin_minmax_add_value(PG_FUNCTION_ARGS)
  * Given an index tuple corresponding to a certain page range and a scan key,
  * return whether the scan key is consistent with the index tuple's min/max
  * values.  Return true if so, false otherwise.
+ *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
  */
 Datum
 brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
 	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -171,7 +185,12 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -180,13 +199,52 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
+	}
+
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
+
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +287,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 1487710d59..33841e14f2 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8191,7 +8191,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------6A37408A2C42B5B56C3B3D49
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210303.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210303.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c          | 158 +++++++++++++++++++-----
 src/backend/access/brin/brin_validate.c |   4 +-
 2 files changed, 126 insertions(+), 36 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..963b7079cf 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,78 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of
+					 * multiple scan keys. We can determine that based on the
+					 * number of arguments - functions with extra parameter
+					 * (number of scan keys) do support this, otherwise we
+					 * have to simply pass the scan keys one by one, as
+					 * before.
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same
+						 * for all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet
+						 * the criteria for a single one of them is enough to
+						 * discard the range as a whole, so break out of the
+						 * loop as soon as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+
+							/* mismatching key, no need to look further  */
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-- 
2.26.2


--------------AC3FFB734F56C5F52D422EFC
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Process-all-scan-keys-in-existing-BRIN-opcl-20210305.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Process-all-scan-keys-in-existing-BRIN-opcl-20210305.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c          | 158 +++++++++++++++++++-----
 src/backend/access/brin/brin_validate.c |   4 +-
 2 files changed, 126 insertions(+), 36 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..f9a0476024 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,78 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any scan keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of
+					 * multiple scan keys. We can determine that based on the
+					 * number of arguments - functions with extra parameter
+					 * (number of scan keys) do support this, otherwise we
+					 * have to simply pass the scan keys one by one, as
+					 * before.
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same
+						 * for all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet
+						 * the criteria for a single one of them is enough to
+						 * discard the range as a whole, so break out of the
+						 * loop as soon as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+
+							/* mismatching key, no need to look further  */
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-- 
2.26.2


--------------82D677E9F94AC7574E460205
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Process-all-scan-keys-in-existing-BRIN-opcl-20210308.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Process-all-scan-keys-in-existing-BRIN-opcl-20210308.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c          | 158 +++++++++++++++++++-----
 src/backend/access/brin/brin_validate.c |   4 +-
 2 files changed, 126 insertions(+), 36 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..f9a0476024 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,78 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any scan keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of
+					 * multiple scan keys. We can determine that based on the
+					 * number of arguments - functions with extra parameter
+					 * (number of scan keys) do support this, otherwise we
+					 * have to simply pass the scan keys one by one, as
+					 * before.
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same
+						 * for all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet
+						 * the criteria for a single one of them is enough to
+						 * discard the range as a whole, so break out of the
+						 * loop as soon as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+
+							/* mismatching key, no need to look further  */
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-- 
2.26.2


--------------556A1DC61262AF15641DB204
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Process-all-scan-keys-in-existing-BRIN-opc-20210308b.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Process-all-scan-keys-in-existing-BRIN-opc-20210308b.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow future opclases to benefit from seeing all keys at once.

This does break existing BRIN opclasses, because the signature of the
consistent function changed. We might support both variants (with 3 and
4 parameters), but that seems pointless - the changes to NULL handling
likely require updates too. So better to make the failure clear. Also,
we're not aware of any out-of-core opclasses - there may be some, but
probably not many.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 doc/src/sgml/brin.sgml                   |   8 +-
 src/backend/access/brin/brin.c           | 118 +++++++++++++------
 src/backend/access/brin/brin_inclusion.c | 140 ++++++++++++++++-------
 src/backend/access/brin/brin_minmax.c    |  92 ++++++++++++---
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 6 files changed, 269 insertions(+), 97 deletions(-)

diff --git a/doc/src/sgml/brin.sgml b/doc/src/sgml/brin.sgml
index 06880c0f7b..078f51bb55 100644
--- a/doc/src/sgml/brin.sgml
+++ b/doc/src/sgml/brin.sgml
@@ -464,12 +464,14 @@ typedef struct BrinOpcInfo
 
    <varlistentry>
     <term><function>bool consistent(BrinDesc *bdesc, BrinValues *column,
-       ScanKey key)</function></term>
+       ScanKey *keys, int nkeys)</function></term>
     <listitem>
      <para>
-      Returns whether the ScanKey is consistent with the given indexed
-      values for a range.
+      Returns whether all the ScanKey entries are consistent with the given
+      indexed values for a range.
       The attribute number to use is passed as part of the scan key.
+      Multiple scan keys for the same attribute may be passed at once, the
+      number of entries is determined by the <literal>nkeys</literal> parameter.
      </para>
     </listitem>
    </varlistentry>
diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..743f2a925a 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,40 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
+					Oid			collation;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
-
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
-
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					/* skip attributes without any scan keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
+
+					bval = &dtup->bt_columns[attno - 1];
+
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * XXX We simply use the collation from the first key (it
+					 * has to be the same for all keys for the same attribue).
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
+					collation = keys[attno - 1][0]->sk_collation;
+
+					/* Check all keys at once */
+					add = FunctionCall4Coll(&consistentFn[attno - 1],
+											collation,
 											PointerGetDatum(bdesc),
 											PointerGetDatum(bval),
-											PointerGetDatum(key));
+											PointerGetDatum(keys[attno - 1]),
+											Int32GetDatum(nkeys[attno - 1]));
 					addrange = DatumGetBool(add);
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..a260074c91 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -251,6 +253,10 @@ brin_inclusion_add_value(PG_FUNCTION_ARGS)
 /*
  * BRIN inclusion consistent function
  *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
+ *
  * All of the strategies are optional.
  */
 Datum
@@ -258,24 +264,31 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/* Handle IS NULL/IS NOT NULL tests */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -284,7 +297,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -293,7 +311,14 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
@@ -301,10 +326,45 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all regular scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* Skip IS NULL/IS NOT NULL keys (already handled above). */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
+	/* This should be called only for regular keys, not for IS [NOT] NULL. */
+	Assert(!(key->sk_flags & SK_ISNULL));
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +384,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +444,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +464,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +483,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +518,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +528,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..e116084a02 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -140,29 +142,41 @@ brin_minmax_add_value(PG_FUNCTION_ARGS)
  * Given an index tuple corresponding to a certain page range and a scan key,
  * return whether the scan key is consistent with the index tuple's min/max
  * values.  Return true if so, false otherwise.
+ *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
  */
 Datum
 brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
 	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -171,7 +185,12 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -180,13 +199,52 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
+	}
+
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
+
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +287,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..2c4f9a3eff 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											4, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index c7619f8cd3..cd1eda38ab 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8223,7 +8223,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------D524CD37E77B36A2883A7617
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Move-IS-NOT-NULL-handling-from-BRIN-support-20210311.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Move-IS-NOT-NULL-handling-from-BRIN-support-20210311.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/9] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 4e0c9be58c..4099e72001 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8191,7 +8191,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------4B194FF8F3EA3786FF9EAE1F
Content-Type: application/vnd.oasis.opendocument.spreadsheet;
 name="brin-bench.ods"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
 filename="brin-bench.ods"

UEsDBBQAAAgAAOO7Q1KFbDmKLgAAAC4AAAAIAAAAbWltZXR5cGVhcHBsaWNhdGlvbi92bmQu
b2FzaXMub3BlbmRvY3VtZW50LnNwcmVhZHNoZWV0UEsDBBQAAAgAAOO7Q1IAAAAAAAAAAAAA
AAAcAAAAQ29uZmlndXJhdGlvbnMyL2FjY2VsZXJhdG9yL1BLAwQUAAAIAADju0NSAAAAAAAA
AAAAAAAAHwAAAENvbmZpZ3VyYXRpb25zMi9pbWFnZXMvQml0bWFwcy9QSwMEFAAACAAA47tD
UgAAAAAAAAAAAAAAABgAAABDb25maWd1cmF0aW9uczIvdG9vbGJhci9QSwMEFAAACAAA47tD
UgAAAAAAAAAAAAAAABgAAABDb25maWd1cmF0aW9uczIvZmxvYXRlci9QSwMEFAAACAAA47tD
UgAAAAAAAAAAAAAAABoAAABDb25maWd1cmF0aW9uczIvcG9wdXBtZW51L1BLAwQUAAAIAADj
u0NSAAAAAAAAAAAAAAAAGAAAAENvbmZpZ3VyYXRpb25zMi9tZW51YmFyL1BLAwQUAAAIAADj
u0NSAAAAAAAAAAAAAAAAGgAAAENvbmZpZ3VyYXRpb25zMi90b29scGFuZWwvUEsDBBQAAAgA
AOO7Q1IAAAAAAAAAAAAAAAAaAAAAQ29uZmlndXJhdGlvbnMyL3N0YXR1c2Jhci9QSwMEFAAA
CAAA47tDUgAAAAAAAAAAAAAAABwAAABDb25maWd1cmF0aW9uczIvcHJvZ3Jlc3NiYXIvUEsD
BBQACAgIAOO7Q1IAAAAAAAAAAAAAAAAMAAAAbWFuaWZlc3QucmRmzZPNboMwEITvPIVlzthA
LwUFcijKuWqfwDWGWAUv8poS3r6Ok1ZRpKrqn9TjrkYz3460m+1hHMiLsqjBVDRjKSXKSGi1
6Ss6uy65pds62ti2Kx+aHfFqg6WfKrp3bio5X5aFLTcMbM+zoih4mvM8T7wiwdU4cUgMxrSO
CAkejUJp9eR8GjnO4glmV1F066CQefcgPYvdOqmgsgphtlK9h7YgkYFAjQlMyoR0gxy6TkvF
M5bzUTnBoe3ix2C904OiPGDwK47P2N6IDKblXuC9sO5cg998lWh67mN6ddPF8d8jlGCcMu5P
6rs7ef/n/i7P/xnir7R2RGxAzqNn+pDntPIfVUevUEsHCLT3aNIFAQAAgwMAAFBLAwQUAAgI
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
qj3ilyQOPhr0ABLtL3rhZyov0EILLbTQQgsttND+W1rqv9n/cfyPtLu9/1v//Op6vYEY/1mt
W6p3rm9s+rFGaz8x2MF6O6wN/SU0Y2o3tvDifH1Jv4qU7vqardljWAZb3pyj1Tq6spysn/fd
2kTWub1a2+VJvKrVtXjeoiYdYprGsV9fxoqz3RtNUinHrl0haYvWpK6ELiWP4mOcD1bNUlgn
6uNKr69UXetjCoGnpsaut8D1spZC5LSaHJ0d1czXz8RDc7d5Xl9JkXeLGk6noLyv069jXdNk
vHUxiHZKk/clm/mSVvMxB7N+Wwrb+ur8Rl5vV7WKquUlh2kYw5Hzcn1uJ5KV344XmvjGZUpE
Stoq+wVtm/1QsoBjNO341mdqLcsKuza3xemjv4aNbm0aIxcZr6vahaTTlXfDKXC0/hPnbbIh
dLuFtK3JJRedK9LWwkv4dazpvPpsU+lmWzg6OQPk79IYL24UG9bslrl36/rubP6q+62s5Pf9
wHc1PnlNpg9l0CfL+PFzjx2XGxkfGnh7uNz5iO/djLTU957HpfBBL+pD0eqTRd9D7o/6e7y+
FvihAf0zWF0OlqCfvepL4Vohc/xLuiQb8JEHU5ZKK8zje+XvT6sPycePmnz4Ht4L/c7BjvxQ
okqyG1PpV7RJyfVaJ3XoNLfogiEllSAVaYLorhsnctwrZOQlenur3985r7+vxDrOVa7h5t79
g2aV7QOJ5jA3Zp3MfkE78spr5nXxXL0erGVDloocPvFtUd4Zmr3e9SJbgfZzf8nBurVNy3Qo
ye30uaENTd1KTi2JhPxyNutjV2NFaXsgTNKB5lK9tJLLyr5x1OeWrIjnTVJcK7mhyCW72Fil
RVKxeefJNrbtTDT4diYsRe0z70dtfGYwi2RAEm5b7UfOj82tm6eHlvLEeapzuaI957ZIJuBl
gM4pTefcynGfv+dXGCXispx2WSvuXdu8BEn6K6f8lk5tdzJYkhnObZP1/Nj3xHPwzGNa+Sog
s/Zr7b7Z3nVVh6qmhiXLeVvlkNdkzlZiYLWrbqpApuj7RLfd5Dy/acdUJWViard6qGJL9HmW
JnV9bG7H1LflgTDpfshB1wvavEn22sPOR5AlmSP9rHDmvp8P8kI+nxX5WC2UIh2V25Hlo+fZ
MrZt2+/VEs/L1vHg3PIeHhmmXbofb0eC/RZaaKGFFlpooYUWWmihhRZaaKGFFlpooYUWWmih
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
--------------4B194FF8F3EA3786FF9EAE1F
Content-Type: application/x-compressed-tar;
 name="brin-stress-test.tgz"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
 filename="brin-stress-test.tgz"

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
4sSJE/vk/y10LU4AkAEA
--------------4B194FF8F3EA3786FF9EAE1F
Content-Type: application/x-compressed-tar;
 name="brin-bench.tgz"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
 filename="brin-bench.tgz"

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
--------------4B194FF8F3EA3786FF9EAE1F--





^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/9] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 4e0c9be58c..4099e72001 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8191,7 +8191,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------0E72B707603BED22B4040825--





^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/9] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 1487710d59..33841e14f2 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8191,7 +8191,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------22A4B241170149838D4D1F8F
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210215.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210215.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 58fe109d2d..8a1a9da78f 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -389,6 +389,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -410,6 +413,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -470,7 +528,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -480,51 +538,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index d7b55f57ea..871e024e00 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8143,7 +8143,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8159,7 +8159,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------CF71AF65F7C337C37C24B045
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210112.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210112.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/6] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 58fe109d2d..8a1a9da78f 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -389,6 +389,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -410,6 +413,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -470,7 +528,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -480,51 +538,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index d7b55f57ea..871e024e00 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8143,7 +8143,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8159,7 +8159,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------D21F32E0F9E7408E9BE1AF2E
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210114.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210114.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/6] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index d27336adcd..f3ead7d53d 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8145,7 +8145,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8161,7 +8161,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------310A2AE1CC4C2E2E77559E3D
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-suppo-20210114-2.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-suppo-20210114-2.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index b5f52d4e4a..2ef11245a8 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8183,7 +8183,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8199,7 +8199,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------FA974B75A0C3E9CA18CE7207
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210122.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210122.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/6] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 158 ++++++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 140 ++++++++++++++------
 src/backend/access/brin/brin_minmax.c    |  92 ++++++++++---
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 303 insertions(+), 95 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..963b7079cf 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,78 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of
+					 * multiple scan keys. We can determine that based on the
+					 * number of arguments - functions with extra parameter
+					 * (number of scan keys) do support this, otherwise we
+					 * have to simply pass the scan keys one by one, as
+					 * before.
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same
+						 * for all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet
+						 * the criteria for a single one of them is enough to
+						 * discard the range as a whole, so break out of the
+						 * loop as soon as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+
+							/* mismatching key, no need to look further  */
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..a260074c91 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -251,6 +253,10 @@ brin_inclusion_add_value(PG_FUNCTION_ARGS)
 /*
  * BRIN inclusion consistent function
  *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
+ *
  * All of the strategies are optional.
  */
 Datum
@@ -258,24 +264,31 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/* Handle IS NULL/IS NOT NULL tests */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -284,7 +297,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -293,7 +311,14 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
@@ -301,10 +326,45 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all regular scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* Skip IS NULL/IS NOT NULL keys (already handled above). */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
+	/* This should be called only for regular keys, not for IS [NOT] NULL. */
+	Assert(!(key->sk_flags & SK_ISNULL));
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +384,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +444,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +464,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +483,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +518,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +528,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..e116084a02 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -140,29 +142,41 @@ brin_minmax_add_value(PG_FUNCTION_ARGS)
  * Given an index tuple corresponding to a certain page range and a scan key,
  * return whether the scan key is consistent with the index tuple's min/max
  * values.  Return true if so, false otherwise.
+ *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
  */
 Datum
 brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
 	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -171,7 +185,12 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -180,13 +199,52 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
+	}
+
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
+
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +287,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 1487710d59..33841e14f2 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8191,7 +8191,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------6A37408A2C42B5B56C3B3D49
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210303.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210303.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c          | 158 +++++++++++++++++++-----
 src/backend/access/brin/brin_validate.c |   4 +-
 2 files changed, 126 insertions(+), 36 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..963b7079cf 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,78 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of
+					 * multiple scan keys. We can determine that based on the
+					 * number of arguments - functions with extra parameter
+					 * (number of scan keys) do support this, otherwise we
+					 * have to simply pass the scan keys one by one, as
+					 * before.
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same
+						 * for all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet
+						 * the criteria for a single one of them is enough to
+						 * discard the range as a whole, so break out of the
+						 * loop as soon as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+
+							/* mismatching key, no need to look further  */
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-- 
2.26.2


--------------AC3FFB734F56C5F52D422EFC
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Process-all-scan-keys-in-existing-BRIN-opcl-20210305.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Process-all-scan-keys-in-existing-BRIN-opcl-20210305.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c          | 158 +++++++++++++++++++-----
 src/backend/access/brin/brin_validate.c |   4 +-
 2 files changed, 126 insertions(+), 36 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..f9a0476024 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,78 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any scan keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of
+					 * multiple scan keys. We can determine that based on the
+					 * number of arguments - functions with extra parameter
+					 * (number of scan keys) do support this, otherwise we
+					 * have to simply pass the scan keys one by one, as
+					 * before.
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same
+						 * for all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet
+						 * the criteria for a single one of them is enough to
+						 * discard the range as a whole, so break out of the
+						 * loop as soon as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+
+							/* mismatching key, no need to look further  */
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-- 
2.26.2


--------------82D677E9F94AC7574E460205
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Process-all-scan-keys-in-existing-BRIN-opcl-20210308.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Process-all-scan-keys-in-existing-BRIN-opcl-20210308.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c          | 158 +++++++++++++++++++-----
 src/backend/access/brin/brin_validate.c |   4 +-
 2 files changed, 126 insertions(+), 36 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..f9a0476024 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,78 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any scan keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of
+					 * multiple scan keys. We can determine that based on the
+					 * number of arguments - functions with extra parameter
+					 * (number of scan keys) do support this, otherwise we
+					 * have to simply pass the scan keys one by one, as
+					 * before.
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same
+						 * for all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet
+						 * the criteria for a single one of them is enough to
+						 * discard the range as a whole, so break out of the
+						 * loop as soon as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+
+							/* mismatching key, no need to look further  */
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-- 
2.26.2


--------------556A1DC61262AF15641DB204
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Process-all-scan-keys-in-existing-BRIN-opc-20210308b.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Process-all-scan-keys-in-existing-BRIN-opc-20210308b.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow future opclases to benefit from seeing all keys at once.

This does break existing BRIN opclasses, because the signature of the
consistent function changed. We might support both variants (with 3 and
4 parameters), but that seems pointless - the changes to NULL handling
likely require updates too. So better to make the failure clear. Also,
we're not aware of any out-of-core opclasses - there may be some, but
probably not many.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 doc/src/sgml/brin.sgml                   |   8 +-
 src/backend/access/brin/brin.c           | 118 +++++++++++++------
 src/backend/access/brin/brin_inclusion.c | 140 ++++++++++++++++-------
 src/backend/access/brin/brin_minmax.c    |  92 ++++++++++++---
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 6 files changed, 269 insertions(+), 97 deletions(-)

diff --git a/doc/src/sgml/brin.sgml b/doc/src/sgml/brin.sgml
index 06880c0f7b..078f51bb55 100644
--- a/doc/src/sgml/brin.sgml
+++ b/doc/src/sgml/brin.sgml
@@ -464,12 +464,14 @@ typedef struct BrinOpcInfo
 
    <varlistentry>
     <term><function>bool consistent(BrinDesc *bdesc, BrinValues *column,
-       ScanKey key)</function></term>
+       ScanKey *keys, int nkeys)</function></term>
     <listitem>
      <para>
-      Returns whether the ScanKey is consistent with the given indexed
-      values for a range.
+      Returns whether all the ScanKey entries are consistent with the given
+      indexed values for a range.
       The attribute number to use is passed as part of the scan key.
+      Multiple scan keys for the same attribute may be passed at once, the
+      number of entries is determined by the <literal>nkeys</literal> parameter.
      </para>
     </listitem>
    </varlistentry>
diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..743f2a925a 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,40 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
+					Oid			collation;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
-
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
-
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					/* skip attributes without any scan keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
+
+					bval = &dtup->bt_columns[attno - 1];
+
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * XXX We simply use the collation from the first key (it
+					 * has to be the same for all keys for the same attribue).
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
+					collation = keys[attno - 1][0]->sk_collation;
+
+					/* Check all keys at once */
+					add = FunctionCall4Coll(&consistentFn[attno - 1],
+											collation,
 											PointerGetDatum(bdesc),
 											PointerGetDatum(bval),
-											PointerGetDatum(key));
+											PointerGetDatum(keys[attno - 1]),
+											Int32GetDatum(nkeys[attno - 1]));
 					addrange = DatumGetBool(add);
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..a260074c91 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -251,6 +253,10 @@ brin_inclusion_add_value(PG_FUNCTION_ARGS)
 /*
  * BRIN inclusion consistent function
  *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
+ *
  * All of the strategies are optional.
  */
 Datum
@@ -258,24 +264,31 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/* Handle IS NULL/IS NOT NULL tests */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -284,7 +297,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -293,7 +311,14 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
@@ -301,10 +326,45 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all regular scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* Skip IS NULL/IS NOT NULL keys (already handled above). */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
+	/* This should be called only for regular keys, not for IS [NOT] NULL. */
+	Assert(!(key->sk_flags & SK_ISNULL));
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +384,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +444,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +464,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +483,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +518,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +528,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..e116084a02 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -140,29 +142,41 @@ brin_minmax_add_value(PG_FUNCTION_ARGS)
  * Given an index tuple corresponding to a certain page range and a scan key,
  * return whether the scan key is consistent with the index tuple's min/max
  * values.  Return true if so, false otherwise.
+ *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
  */
 Datum
 brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
 	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -171,7 +185,12 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -180,13 +199,52 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
+	}
+
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
+
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +287,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..2c4f9a3eff 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											4, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index c7619f8cd3..cd1eda38ab 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8223,7 +8223,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------D524CD37E77B36A2883A7617
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Move-IS-NOT-NULL-handling-from-BRIN-support-20210311.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Move-IS-NOT-NULL-handling-from-BRIN-support-20210311.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/9] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 4e0c9be58c..4099e72001 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8191,7 +8191,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------4B194FF8F3EA3786FF9EAE1F
Content-Type: application/vnd.oasis.opendocument.spreadsheet;
 name="brin-bench.ods"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
 filename="brin-bench.ods"

UEsDBBQAAAgAAOO7Q1KFbDmKLgAAAC4AAAAIAAAAbWltZXR5cGVhcHBsaWNhdGlvbi92bmQu
b2FzaXMub3BlbmRvY3VtZW50LnNwcmVhZHNoZWV0UEsDBBQAAAgAAOO7Q1IAAAAAAAAAAAAA
AAAcAAAAQ29uZmlndXJhdGlvbnMyL2FjY2VsZXJhdG9yL1BLAwQUAAAIAADju0NSAAAAAAAA
AAAAAAAAHwAAAENvbmZpZ3VyYXRpb25zMi9pbWFnZXMvQml0bWFwcy9QSwMEFAAACAAA47tD
UgAAAAAAAAAAAAAAABgAAABDb25maWd1cmF0aW9uczIvdG9vbGJhci9QSwMEFAAACAAA47tD
UgAAAAAAAAAAAAAAABgAAABDb25maWd1cmF0aW9uczIvZmxvYXRlci9QSwMEFAAACAAA47tD
UgAAAAAAAAAAAAAAABoAAABDb25maWd1cmF0aW9uczIvcG9wdXBtZW51L1BLAwQUAAAIAADj
u0NSAAAAAAAAAAAAAAAAGAAAAENvbmZpZ3VyYXRpb25zMi9tZW51YmFyL1BLAwQUAAAIAADj
u0NSAAAAAAAAAAAAAAAAGgAAAENvbmZpZ3VyYXRpb25zMi90b29scGFuZWwvUEsDBBQAAAgA
AOO7Q1IAAAAAAAAAAAAAAAAaAAAAQ29uZmlndXJhdGlvbnMyL3N0YXR1c2Jhci9QSwMEFAAA
CAAA47tDUgAAAAAAAAAAAAAAABwAAABDb25maWd1cmF0aW9uczIvcHJvZ3Jlc3NiYXIvUEsD
BBQACAgIAOO7Q1IAAAAAAAAAAAAAAAAMAAAAbWFuaWZlc3QucmRmzZPNboMwEITvPIVlzthA
LwUFcijKuWqfwDWGWAUv8poS3r6Ok1ZRpKrqn9TjrkYz3460m+1hHMiLsqjBVDRjKSXKSGi1
6Ss6uy65pds62ti2Kx+aHfFqg6WfKrp3bio5X5aFLTcMbM+zoih4mvM8T7wiwdU4cUgMxrSO
CAkejUJp9eR8GjnO4glmV1F066CQefcgPYvdOqmgsgphtlK9h7YgkYFAjQlMyoR0gxy6TkvF
M5bzUTnBoe3ix2C904OiPGDwK47P2N6IDKblXuC9sO5cg998lWh67mN6ddPF8d8jlGCcMu5P
6rs7ef/n/i7P/xnir7R2RGxAzqNn+pDntPIfVUevUEsHCLT3aNIFAQAAgwMAAFBLAwQUAAgI
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
qj3ilyQOPhr0ABLtL3rhZyov0EILLbTQQgsttND+W1rqv9n/cfyPtLu9/1v//Op6vYEY/1mt
W6p3rm9s+rFGaz8x2MF6O6wN/SU0Y2o3tvDifH1Jv4qU7vqardljWAZb3pyj1Tq6spysn/fd
2kTWub1a2+VJvKrVtXjeoiYdYprGsV9fxoqz3RtNUinHrl0haYvWpK6ELiWP4mOcD1bNUlgn
6uNKr69UXetjCoGnpsaut8D1spZC5LSaHJ0d1czXz8RDc7d5Xl9JkXeLGk6noLyv069jXdNk
vHUxiHZKk/clm/mSVvMxB7N+Wwrb+ur8Rl5vV7WKquUlh2kYw5Hzcn1uJ5KV344XmvjGZUpE
Stoq+wVtm/1QsoBjNO341mdqLcsKuza3xemjv4aNbm0aIxcZr6vahaTTlXfDKXC0/hPnbbIh
dLuFtK3JJRedK9LWwkv4dazpvPpsU+lmWzg6OQPk79IYL24UG9bslrl36/rubP6q+62s5Pf9
wHc1PnlNpg9l0CfL+PFzjx2XGxkfGnh7uNz5iO/djLTU957HpfBBL+pD0eqTRd9D7o/6e7y+
FvihAf0zWF0OlqCfvepL4Vohc/xLuiQb8JEHU5ZKK8zje+XvT6sPycePmnz4Ht4L/c7BjvxQ
okqyG1PpV7RJyfVaJ3XoNLfogiEllSAVaYLorhsnctwrZOQlenur3985r7+vxDrOVa7h5t79
g2aV7QOJ5jA3Zp3MfkE78spr5nXxXL0erGVDloocPvFtUd4Zmr3e9SJbgfZzf8nBurVNy3Qo
ye30uaENTd1KTi2JhPxyNutjV2NFaXsgTNKB5lK9tJLLyr5x1OeWrIjnTVJcK7mhyCW72Fil
RVKxeefJNrbtTDT4diYsRe0z70dtfGYwi2RAEm5b7UfOj82tm6eHlvLEeapzuaI957ZIJuBl
gM4pTefcynGfv+dXGCXispx2WSvuXdu8BEn6K6f8lk5tdzJYkhnObZP1/Nj3xHPwzGNa+Sog
s/Zr7b7Z3nVVh6qmhiXLeVvlkNdkzlZiYLWrbqpApuj7RLfd5Dy/acdUJWViard6qGJL9HmW
JnV9bG7H1LflgTDpfshB1wvavEn22sPOR5AlmSP9rHDmvp8P8kI+nxX5WC2UIh2V25Hlo+fZ
MrZt2+/VEs/L1vHg3PIeHhmmXbofb0eC/RZaaKGFFlpooYUWWmihhRZaaKGFFlpooYUWWmih
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
--------------4B194FF8F3EA3786FF9EAE1F
Content-Type: application/x-compressed-tar;
 name="brin-stress-test.tgz"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
 filename="brin-stress-test.tgz"

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
4sSJE/vk/y10LU4AkAEA
--------------4B194FF8F3EA3786FF9EAE1F
Content-Type: application/x-compressed-tar;
 name="brin-bench.tgz"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
 filename="brin-bench.tgz"

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
--------------4B194FF8F3EA3786FF9EAE1F--





^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/9] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 4e0c9be58c..4099e72001 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8191,7 +8191,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------0E72B707603BED22B4040825--





^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/9] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 1487710d59..33841e14f2 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8191,7 +8191,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------22A4B241170149838D4D1F8F
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210215.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210215.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/6] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 158 ++++++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 140 ++++++++++++++------
 src/backend/access/brin/brin_minmax.c    |  92 ++++++++++---
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 303 insertions(+), 95 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..963b7079cf 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,78 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of
+					 * multiple scan keys. We can determine that based on the
+					 * number of arguments - functions with extra parameter
+					 * (number of scan keys) do support this, otherwise we
+					 * have to simply pass the scan keys one by one, as
+					 * before.
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same
+						 * for all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet
+						 * the criteria for a single one of them is enough to
+						 * discard the range as a whole, so break out of the
+						 * loop as soon as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+
+							/* mismatching key, no need to look further  */
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..a260074c91 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -251,6 +253,10 @@ brin_inclusion_add_value(PG_FUNCTION_ARGS)
 /*
  * BRIN inclusion consistent function
  *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
+ *
  * All of the strategies are optional.
  */
 Datum
@@ -258,24 +264,31 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/* Handle IS NULL/IS NOT NULL tests */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -284,7 +297,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -293,7 +311,14 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
@@ -301,10 +326,45 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all regular scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* Skip IS NULL/IS NOT NULL keys (already handled above). */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
+	/* This should be called only for regular keys, not for IS [NOT] NULL. */
+	Assert(!(key->sk_flags & SK_ISNULL));
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +384,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +444,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +464,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +483,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +518,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +528,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..e116084a02 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -140,29 +142,41 @@ brin_minmax_add_value(PG_FUNCTION_ARGS)
  * Given an index tuple corresponding to a certain page range and a scan key,
  * return whether the scan key is consistent with the index tuple's min/max
  * values.  Return true if so, false otherwise.
+ *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
  */
 Datum
 brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
 	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -171,7 +185,12 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -180,13 +199,52 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
+	}
+
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
+
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +287,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 1487710d59..33841e14f2 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8191,7 +8191,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------6A37408A2C42B5B56C3B3D49
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210303.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210303.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c          | 158 +++++++++++++++++++-----
 src/backend/access/brin/brin_validate.c |   4 +-
 2 files changed, 126 insertions(+), 36 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..963b7079cf 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,78 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of
+					 * multiple scan keys. We can determine that based on the
+					 * number of arguments - functions with extra parameter
+					 * (number of scan keys) do support this, otherwise we
+					 * have to simply pass the scan keys one by one, as
+					 * before.
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same
+						 * for all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet
+						 * the criteria for a single one of them is enough to
+						 * discard the range as a whole, so break out of the
+						 * loop as soon as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+
+							/* mismatching key, no need to look further  */
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-- 
2.26.2


--------------AC3FFB734F56C5F52D422EFC
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Process-all-scan-keys-in-existing-BRIN-opcl-20210305.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Process-all-scan-keys-in-existing-BRIN-opcl-20210305.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c          | 158 +++++++++++++++++++-----
 src/backend/access/brin/brin_validate.c |   4 +-
 2 files changed, 126 insertions(+), 36 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..f9a0476024 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,78 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any scan keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of
+					 * multiple scan keys. We can determine that based on the
+					 * number of arguments - functions with extra parameter
+					 * (number of scan keys) do support this, otherwise we
+					 * have to simply pass the scan keys one by one, as
+					 * before.
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same
+						 * for all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet
+						 * the criteria for a single one of them is enough to
+						 * discard the range as a whole, so break out of the
+						 * loop as soon as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+
+							/* mismatching key, no need to look further  */
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-- 
2.26.2


--------------82D677E9F94AC7574E460205
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Process-all-scan-keys-in-existing-BRIN-opcl-20210308.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Process-all-scan-keys-in-existing-BRIN-opcl-20210308.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c          | 158 +++++++++++++++++++-----
 src/backend/access/brin/brin_validate.c |   4 +-
 2 files changed, 126 insertions(+), 36 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..f9a0476024 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,78 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any scan keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of
+					 * multiple scan keys. We can determine that based on the
+					 * number of arguments - functions with extra parameter
+					 * (number of scan keys) do support this, otherwise we
+					 * have to simply pass the scan keys one by one, as
+					 * before.
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same
+						 * for all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet
+						 * the criteria for a single one of them is enough to
+						 * discard the range as a whole, so break out of the
+						 * loop as soon as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+
+							/* mismatching key, no need to look further  */
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-- 
2.26.2


--------------556A1DC61262AF15641DB204
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Process-all-scan-keys-in-existing-BRIN-opc-20210308b.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Process-all-scan-keys-in-existing-BRIN-opc-20210308b.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow future opclases to benefit from seeing all keys at once.

This does break existing BRIN opclasses, because the signature of the
consistent function changed. We might support both variants (with 3 and
4 parameters), but that seems pointless - the changes to NULL handling
likely require updates too. So better to make the failure clear. Also,
we're not aware of any out-of-core opclasses - there may be some, but
probably not many.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 doc/src/sgml/brin.sgml                   |   8 +-
 src/backend/access/brin/brin.c           | 118 +++++++++++++------
 src/backend/access/brin/brin_inclusion.c | 140 ++++++++++++++++-------
 src/backend/access/brin/brin_minmax.c    |  92 ++++++++++++---
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 6 files changed, 269 insertions(+), 97 deletions(-)

diff --git a/doc/src/sgml/brin.sgml b/doc/src/sgml/brin.sgml
index 06880c0f7b..078f51bb55 100644
--- a/doc/src/sgml/brin.sgml
+++ b/doc/src/sgml/brin.sgml
@@ -464,12 +464,14 @@ typedef struct BrinOpcInfo
 
    <varlistentry>
     <term><function>bool consistent(BrinDesc *bdesc, BrinValues *column,
-       ScanKey key)</function></term>
+       ScanKey *keys, int nkeys)</function></term>
     <listitem>
      <para>
-      Returns whether the ScanKey is consistent with the given indexed
-      values for a range.
+      Returns whether all the ScanKey entries are consistent with the given
+      indexed values for a range.
       The attribute number to use is passed as part of the scan key.
+      Multiple scan keys for the same attribute may be passed at once, the
+      number of entries is determined by the <literal>nkeys</literal> parameter.
      </para>
     </listitem>
    </varlistentry>
diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..743f2a925a 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,40 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
+					Oid			collation;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
-
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
-
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					/* skip attributes without any scan keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
+
+					bval = &dtup->bt_columns[attno - 1];
+
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * XXX We simply use the collation from the first key (it
+					 * has to be the same for all keys for the same attribue).
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
+					collation = keys[attno - 1][0]->sk_collation;
+
+					/* Check all keys at once */
+					add = FunctionCall4Coll(&consistentFn[attno - 1],
+											collation,
 											PointerGetDatum(bdesc),
 											PointerGetDatum(bval),
-											PointerGetDatum(key));
+											PointerGetDatum(keys[attno - 1]),
+											Int32GetDatum(nkeys[attno - 1]));
 					addrange = DatumGetBool(add);
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..a260074c91 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -251,6 +253,10 @@ brin_inclusion_add_value(PG_FUNCTION_ARGS)
 /*
  * BRIN inclusion consistent function
  *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
+ *
  * All of the strategies are optional.
  */
 Datum
@@ -258,24 +264,31 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/* Handle IS NULL/IS NOT NULL tests */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -284,7 +297,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -293,7 +311,14 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
@@ -301,10 +326,45 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all regular scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* Skip IS NULL/IS NOT NULL keys (already handled above). */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
+	/* This should be called only for regular keys, not for IS [NOT] NULL. */
+	Assert(!(key->sk_flags & SK_ISNULL));
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +384,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +444,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +464,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +483,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +518,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +528,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..e116084a02 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -140,29 +142,41 @@ brin_minmax_add_value(PG_FUNCTION_ARGS)
  * Given an index tuple corresponding to a certain page range and a scan key,
  * return whether the scan key is consistent with the index tuple's min/max
  * values.  Return true if so, false otherwise.
+ *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
  */
 Datum
 brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
 	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -171,7 +185,12 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -180,13 +199,52 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
+	}
+
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
+
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +287,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..2c4f9a3eff 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											4, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index c7619f8cd3..cd1eda38ab 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8223,7 +8223,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------D524CD37E77B36A2883A7617
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Move-IS-NOT-NULL-handling-from-BRIN-support-20210311.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Move-IS-NOT-NULL-handling-from-BRIN-support-20210311.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/9] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 4e0c9be58c..4099e72001 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8191,7 +8191,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------4B194FF8F3EA3786FF9EAE1F
Content-Type: application/vnd.oasis.opendocument.spreadsheet;
 name="brin-bench.ods"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
 filename="brin-bench.ods"

UEsDBBQAAAgAAOO7Q1KFbDmKLgAAAC4AAAAIAAAAbWltZXR5cGVhcHBsaWNhdGlvbi92bmQu
b2FzaXMub3BlbmRvY3VtZW50LnNwcmVhZHNoZWV0UEsDBBQAAAgAAOO7Q1IAAAAAAAAAAAAA
AAAcAAAAQ29uZmlndXJhdGlvbnMyL2FjY2VsZXJhdG9yL1BLAwQUAAAIAADju0NSAAAAAAAA
AAAAAAAAHwAAAENvbmZpZ3VyYXRpb25zMi9pbWFnZXMvQml0bWFwcy9QSwMEFAAACAAA47tD
UgAAAAAAAAAAAAAAABgAAABDb25maWd1cmF0aW9uczIvdG9vbGJhci9QSwMEFAAACAAA47tD
UgAAAAAAAAAAAAAAABgAAABDb25maWd1cmF0aW9uczIvZmxvYXRlci9QSwMEFAAACAAA47tD
UgAAAAAAAAAAAAAAABoAAABDb25maWd1cmF0aW9uczIvcG9wdXBtZW51L1BLAwQUAAAIAADj
u0NSAAAAAAAAAAAAAAAAGAAAAENvbmZpZ3VyYXRpb25zMi9tZW51YmFyL1BLAwQUAAAIAADj
u0NSAAAAAAAAAAAAAAAAGgAAAENvbmZpZ3VyYXRpb25zMi90b29scGFuZWwvUEsDBBQAAAgA
AOO7Q1IAAAAAAAAAAAAAAAAaAAAAQ29uZmlndXJhdGlvbnMyL3N0YXR1c2Jhci9QSwMEFAAA
CAAA47tDUgAAAAAAAAAAAAAAABwAAABDb25maWd1cmF0aW9uczIvcHJvZ3Jlc3NiYXIvUEsD
BBQACAgIAOO7Q1IAAAAAAAAAAAAAAAAMAAAAbWFuaWZlc3QucmRmzZPNboMwEITvPIVlzthA
LwUFcijKuWqfwDWGWAUv8poS3r6Ok1ZRpKrqn9TjrkYz3460m+1hHMiLsqjBVDRjKSXKSGi1
6Ss6uy65pds62ti2Kx+aHfFqg6WfKrp3bio5X5aFLTcMbM+zoih4mvM8T7wiwdU4cUgMxrSO
CAkejUJp9eR8GjnO4glmV1F066CQefcgPYvdOqmgsgphtlK9h7YgkYFAjQlMyoR0gxy6TkvF
M5bzUTnBoe3ix2C904OiPGDwK47P2N6IDKblXuC9sO5cg998lWh67mN6ddPF8d8jlGCcMu5P
6rs7ef/n/i7P/xnir7R2RGxAzqNn+pDntPIfVUevUEsHCLT3aNIFAQAAgwMAAFBLAwQUAAgI
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
qj3ilyQOPhr0ABLtL3rhZyov0EILLbTQQgsttND+W1rqv9n/cfyPtLu9/1v//Op6vYEY/1mt
W6p3rm9s+rFGaz8x2MF6O6wN/SU0Y2o3tvDifH1Jv4qU7vqardljWAZb3pyj1Tq6spysn/fd
2kTWub1a2+VJvKrVtXjeoiYdYprGsV9fxoqz3RtNUinHrl0haYvWpK6ELiWP4mOcD1bNUlgn
6uNKr69UXetjCoGnpsaut8D1spZC5LSaHJ0d1czXz8RDc7d5Xl9JkXeLGk6noLyv069jXdNk
vHUxiHZKk/clm/mSVvMxB7N+Wwrb+ur8Rl5vV7WKquUlh2kYw5Hzcn1uJ5KV344XmvjGZUpE
Stoq+wVtm/1QsoBjNO341mdqLcsKuza3xemjv4aNbm0aIxcZr6vahaTTlXfDKXC0/hPnbbIh
dLuFtK3JJRedK9LWwkv4dazpvPpsU+lmWzg6OQPk79IYL24UG9bslrl36/rubP6q+62s5Pf9
wHc1PnlNpg9l0CfL+PFzjx2XGxkfGnh7uNz5iO/djLTU957HpfBBL+pD0eqTRd9D7o/6e7y+
FvihAf0zWF0OlqCfvepL4Vohc/xLuiQb8JEHU5ZKK8zje+XvT6sPycePmnz4Ht4L/c7BjvxQ
okqyG1PpV7RJyfVaJ3XoNLfogiEllSAVaYLorhsnctwrZOQlenur3985r7+vxDrOVa7h5t79
g2aV7QOJ5jA3Zp3MfkE78spr5nXxXL0erGVDloocPvFtUd4Zmr3e9SJbgfZzf8nBurVNy3Qo
ye30uaENTd1KTi2JhPxyNutjV2NFaXsgTNKB5lK9tJLLyr5x1OeWrIjnTVJcK7mhyCW72Fil
RVKxeefJNrbtTDT4diYsRe0z70dtfGYwi2RAEm5b7UfOj82tm6eHlvLEeapzuaI957ZIJuBl
gM4pTefcynGfv+dXGCXispx2WSvuXdu8BEn6K6f8lk5tdzJYkhnObZP1/Nj3xHPwzGNa+Sog
s/Zr7b7Z3nVVh6qmhiXLeVvlkNdkzlZiYLWrbqpApuj7RLfd5Dy/acdUJWViard6qGJL9HmW
JnV9bG7H1LflgTDpfshB1wvavEn22sPOR5AlmSP9rHDmvp8P8kI+nxX5WC2UIh2V25Hlo+fZ
MrZt2+/VEs/L1vHg3PIeHhmmXbofb0eC/RZaaKGFFlpooYUWWmihhRZaaKGFFlpooYUWWmih
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
--------------4B194FF8F3EA3786FF9EAE1F
Content-Type: application/x-compressed-tar;
 name="brin-stress-test.tgz"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
 filename="brin-stress-test.tgz"

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
4sSJE/vk/y10LU4AkAEA
--------------4B194FF8F3EA3786FF9EAE1F
Content-Type: application/x-compressed-tar;
 name="brin-bench.tgz"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
 filename="brin-bench.tgz"

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
--------------4B194FF8F3EA3786FF9EAE1F--





^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/9] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 4e0c9be58c..4099e72001 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8191,7 +8191,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------0E72B707603BED22B4040825--





^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/9] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 1487710d59..33841e14f2 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8191,7 +8191,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------22A4B241170149838D4D1F8F
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210215.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210215.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 58fe109d2d..8a1a9da78f 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -389,6 +389,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -410,6 +413,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -470,7 +528,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -480,51 +538,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index d7b55f57ea..871e024e00 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8143,7 +8143,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8159,7 +8159,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------CF71AF65F7C337C37C24B045
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210112.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210112.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/6] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 58fe109d2d..8a1a9da78f 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -389,6 +389,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -410,6 +413,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -470,7 +528,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -480,51 +538,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index d7b55f57ea..871e024e00 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8143,7 +8143,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8159,7 +8159,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------D21F32E0F9E7408E9BE1AF2E
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210114.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210114.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/6] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index d27336adcd..f3ead7d53d 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8145,7 +8145,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8161,7 +8161,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------310A2AE1CC4C2E2E77559E3D
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-suppo-20210114-2.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-suppo-20210114-2.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index b5f52d4e4a..2ef11245a8 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8183,7 +8183,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8199,7 +8199,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------FA974B75A0C3E9CA18CE7207
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210122.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210122.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/6] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 158 ++++++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 140 ++++++++++++++------
 src/backend/access/brin/brin_minmax.c    |  92 ++++++++++---
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 303 insertions(+), 95 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..963b7079cf 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,78 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of
+					 * multiple scan keys. We can determine that based on the
+					 * number of arguments - functions with extra parameter
+					 * (number of scan keys) do support this, otherwise we
+					 * have to simply pass the scan keys one by one, as
+					 * before.
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same
+						 * for all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet
+						 * the criteria for a single one of them is enough to
+						 * discard the range as a whole, so break out of the
+						 * loop as soon as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+
+							/* mismatching key, no need to look further  */
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..a260074c91 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -251,6 +253,10 @@ brin_inclusion_add_value(PG_FUNCTION_ARGS)
 /*
  * BRIN inclusion consistent function
  *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
+ *
  * All of the strategies are optional.
  */
 Datum
@@ -258,24 +264,31 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/* Handle IS NULL/IS NOT NULL tests */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -284,7 +297,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -293,7 +311,14 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
@@ -301,10 +326,45 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all regular scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* Skip IS NULL/IS NOT NULL keys (already handled above). */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
+	/* This should be called only for regular keys, not for IS [NOT] NULL. */
+	Assert(!(key->sk_flags & SK_ISNULL));
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +384,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +444,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +464,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +483,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +518,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +528,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..e116084a02 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -140,29 +142,41 @@ brin_minmax_add_value(PG_FUNCTION_ARGS)
  * Given an index tuple corresponding to a certain page range and a scan key,
  * return whether the scan key is consistent with the index tuple's min/max
  * values.  Return true if so, false otherwise.
+ *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
  */
 Datum
 brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
 	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -171,7 +185,12 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -180,13 +199,52 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
+	}
+
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
+
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +287,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 1487710d59..33841e14f2 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8191,7 +8191,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------6A37408A2C42B5B56C3B3D49
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210303.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210303.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c          | 158 +++++++++++++++++++-----
 src/backend/access/brin/brin_validate.c |   4 +-
 2 files changed, 126 insertions(+), 36 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..963b7079cf 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,78 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of
+					 * multiple scan keys. We can determine that based on the
+					 * number of arguments - functions with extra parameter
+					 * (number of scan keys) do support this, otherwise we
+					 * have to simply pass the scan keys one by one, as
+					 * before.
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same
+						 * for all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet
+						 * the criteria for a single one of them is enough to
+						 * discard the range as a whole, so break out of the
+						 * loop as soon as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+
+							/* mismatching key, no need to look further  */
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-- 
2.26.2


--------------AC3FFB734F56C5F52D422EFC
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Process-all-scan-keys-in-existing-BRIN-opcl-20210305.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Process-all-scan-keys-in-existing-BRIN-opcl-20210305.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c          | 158 +++++++++++++++++++-----
 src/backend/access/brin/brin_validate.c |   4 +-
 2 files changed, 126 insertions(+), 36 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..f9a0476024 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,78 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any scan keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of
+					 * multiple scan keys. We can determine that based on the
+					 * number of arguments - functions with extra parameter
+					 * (number of scan keys) do support this, otherwise we
+					 * have to simply pass the scan keys one by one, as
+					 * before.
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same
+						 * for all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet
+						 * the criteria for a single one of them is enough to
+						 * discard the range as a whole, so break out of the
+						 * loop as soon as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+
+							/* mismatching key, no need to look further  */
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-- 
2.26.2


--------------82D677E9F94AC7574E460205
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Process-all-scan-keys-in-existing-BRIN-opcl-20210308.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Process-all-scan-keys-in-existing-BRIN-opcl-20210308.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c          | 158 +++++++++++++++++++-----
 src/backend/access/brin/brin_validate.c |   4 +-
 2 files changed, 126 insertions(+), 36 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..f9a0476024 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,78 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any scan keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of
+					 * multiple scan keys. We can determine that based on the
+					 * number of arguments - functions with extra parameter
+					 * (number of scan keys) do support this, otherwise we
+					 * have to simply pass the scan keys one by one, as
+					 * before.
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same
+						 * for all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet
+						 * the criteria for a single one of them is enough to
+						 * discard the range as a whole, so break out of the
+						 * loop as soon as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+
+							/* mismatching key, no need to look further  */
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-- 
2.26.2


--------------556A1DC61262AF15641DB204
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Process-all-scan-keys-in-existing-BRIN-opc-20210308b.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Process-all-scan-keys-in-existing-BRIN-opc-20210308b.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow future opclases to benefit from seeing all keys at once.

This does break existing BRIN opclasses, because the signature of the
consistent function changed. We might support both variants (with 3 and
4 parameters), but that seems pointless - the changes to NULL handling
likely require updates too. So better to make the failure clear. Also,
we're not aware of any out-of-core opclasses - there may be some, but
probably not many.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 doc/src/sgml/brin.sgml                   |   8 +-
 src/backend/access/brin/brin.c           | 118 +++++++++++++------
 src/backend/access/brin/brin_inclusion.c | 140 ++++++++++++++++-------
 src/backend/access/brin/brin_minmax.c    |  92 ++++++++++++---
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 6 files changed, 269 insertions(+), 97 deletions(-)

diff --git a/doc/src/sgml/brin.sgml b/doc/src/sgml/brin.sgml
index 06880c0f7b..078f51bb55 100644
--- a/doc/src/sgml/brin.sgml
+++ b/doc/src/sgml/brin.sgml
@@ -464,12 +464,14 @@ typedef struct BrinOpcInfo
 
    <varlistentry>
     <term><function>bool consistent(BrinDesc *bdesc, BrinValues *column,
-       ScanKey key)</function></term>
+       ScanKey *keys, int nkeys)</function></term>
     <listitem>
      <para>
-      Returns whether the ScanKey is consistent with the given indexed
-      values for a range.
+      Returns whether all the ScanKey entries are consistent with the given
+      indexed values for a range.
       The attribute number to use is passed as part of the scan key.
+      Multiple scan keys for the same attribute may be passed at once, the
+      number of entries is determined by the <literal>nkeys</literal> parameter.
      </para>
     </listitem>
    </varlistentry>
diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..743f2a925a 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,40 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
+					Oid			collation;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
-
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
-
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					/* skip attributes without any scan keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
+
+					bval = &dtup->bt_columns[attno - 1];
+
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * XXX We simply use the collation from the first key (it
+					 * has to be the same for all keys for the same attribue).
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
+					collation = keys[attno - 1][0]->sk_collation;
+
+					/* Check all keys at once */
+					add = FunctionCall4Coll(&consistentFn[attno - 1],
+											collation,
 											PointerGetDatum(bdesc),
 											PointerGetDatum(bval),
-											PointerGetDatum(key));
+											PointerGetDatum(keys[attno - 1]),
+											Int32GetDatum(nkeys[attno - 1]));
 					addrange = DatumGetBool(add);
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..a260074c91 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -251,6 +253,10 @@ brin_inclusion_add_value(PG_FUNCTION_ARGS)
 /*
  * BRIN inclusion consistent function
  *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
+ *
  * All of the strategies are optional.
  */
 Datum
@@ -258,24 +264,31 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/* Handle IS NULL/IS NOT NULL tests */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -284,7 +297,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -293,7 +311,14 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
@@ -301,10 +326,45 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all regular scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* Skip IS NULL/IS NOT NULL keys (already handled above). */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
+	/* This should be called only for regular keys, not for IS [NOT] NULL. */
+	Assert(!(key->sk_flags & SK_ISNULL));
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +384,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +444,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +464,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +483,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +518,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +528,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..e116084a02 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -140,29 +142,41 @@ brin_minmax_add_value(PG_FUNCTION_ARGS)
  * Given an index tuple corresponding to a certain page range and a scan key,
  * return whether the scan key is consistent with the index tuple's min/max
  * values.  Return true if so, false otherwise.
+ *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
  */
 Datum
 brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
 	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -171,7 +185,12 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -180,13 +199,52 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
+	}
+
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
+
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +287,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..2c4f9a3eff 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											4, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index c7619f8cd3..cd1eda38ab 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8223,7 +8223,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------D524CD37E77B36A2883A7617
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Move-IS-NOT-NULL-handling-from-BRIN-support-20210311.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Move-IS-NOT-NULL-handling-from-BRIN-support-20210311.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/9] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 4e0c9be58c..4099e72001 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8191,7 +8191,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------4B194FF8F3EA3786FF9EAE1F
Content-Type: application/vnd.oasis.opendocument.spreadsheet;
 name="brin-bench.ods"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
 filename="brin-bench.ods"

UEsDBBQAAAgAAOO7Q1KFbDmKLgAAAC4AAAAIAAAAbWltZXR5cGVhcHBsaWNhdGlvbi92bmQu
b2FzaXMub3BlbmRvY3VtZW50LnNwcmVhZHNoZWV0UEsDBBQAAAgAAOO7Q1IAAAAAAAAAAAAA
AAAcAAAAQ29uZmlndXJhdGlvbnMyL2FjY2VsZXJhdG9yL1BLAwQUAAAIAADju0NSAAAAAAAA
AAAAAAAAHwAAAENvbmZpZ3VyYXRpb25zMi9pbWFnZXMvQml0bWFwcy9QSwMEFAAACAAA47tD
UgAAAAAAAAAAAAAAABgAAABDb25maWd1cmF0aW9uczIvdG9vbGJhci9QSwMEFAAACAAA47tD
UgAAAAAAAAAAAAAAABgAAABDb25maWd1cmF0aW9uczIvZmxvYXRlci9QSwMEFAAACAAA47tD
UgAAAAAAAAAAAAAAABoAAABDb25maWd1cmF0aW9uczIvcG9wdXBtZW51L1BLAwQUAAAIAADj
u0NSAAAAAAAAAAAAAAAAGAAAAENvbmZpZ3VyYXRpb25zMi9tZW51YmFyL1BLAwQUAAAIAADj
u0NSAAAAAAAAAAAAAAAAGgAAAENvbmZpZ3VyYXRpb25zMi90b29scGFuZWwvUEsDBBQAAAgA
AOO7Q1IAAAAAAAAAAAAAAAAaAAAAQ29uZmlndXJhdGlvbnMyL3N0YXR1c2Jhci9QSwMEFAAA
CAAA47tDUgAAAAAAAAAAAAAAABwAAABDb25maWd1cmF0aW9uczIvcHJvZ3Jlc3NiYXIvUEsD
BBQACAgIAOO7Q1IAAAAAAAAAAAAAAAAMAAAAbWFuaWZlc3QucmRmzZPNboMwEITvPIVlzthA
LwUFcijKuWqfwDWGWAUv8poS3r6Ok1ZRpKrqn9TjrkYz3460m+1hHMiLsqjBVDRjKSXKSGi1
6Ss6uy65pds62ti2Kx+aHfFqg6WfKrp3bio5X5aFLTcMbM+zoih4mvM8T7wiwdU4cUgMxrSO
CAkejUJp9eR8GjnO4glmV1F066CQefcgPYvdOqmgsgphtlK9h7YgkYFAjQlMyoR0gxy6TkvF
M5bzUTnBoe3ix2C904OiPGDwK47P2N6IDKblXuC9sO5cg998lWh67mN6ddPF8d8jlGCcMu5P
6rs7ef/n/i7P/xnir7R2RGxAzqNn+pDntPIfVUevUEsHCLT3aNIFAQAAgwMAAFBLAwQUAAgI
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
qj3ilyQOPhr0ABLtL3rhZyov0EILLbTQQgsttND+W1rqv9n/cfyPtLu9/1v//Op6vYEY/1mt
W6p3rm9s+rFGaz8x2MF6O6wN/SU0Y2o3tvDifH1Jv4qU7vqardljWAZb3pyj1Tq6spysn/fd
2kTWub1a2+VJvKrVtXjeoiYdYprGsV9fxoqz3RtNUinHrl0haYvWpK6ELiWP4mOcD1bNUlgn
6uNKr69UXetjCoGnpsaut8D1spZC5LSaHJ0d1czXz8RDc7d5Xl9JkXeLGk6noLyv069jXdNk
vHUxiHZKk/clm/mSVvMxB7N+Wwrb+ur8Rl5vV7WKquUlh2kYw5Hzcn1uJ5KV344XmvjGZUpE
Stoq+wVtm/1QsoBjNO341mdqLcsKuza3xemjv4aNbm0aIxcZr6vahaTTlXfDKXC0/hPnbbIh
dLuFtK3JJRedK9LWwkv4dazpvPpsU+lmWzg6OQPk79IYL24UG9bslrl36/rubP6q+62s5Pf9
wHc1PnlNpg9l0CfL+PFzjx2XGxkfGnh7uNz5iO/djLTU957HpfBBL+pD0eqTRd9D7o/6e7y+
FvihAf0zWF0OlqCfvepL4Vohc/xLuiQb8JEHU5ZKK8zje+XvT6sPycePmnz4Ht4L/c7BjvxQ
okqyG1PpV7RJyfVaJ3XoNLfogiEllSAVaYLorhsnctwrZOQlenur3985r7+vxDrOVa7h5t79
g2aV7QOJ5jA3Zp3MfkE78spr5nXxXL0erGVDloocPvFtUd4Zmr3e9SJbgfZzf8nBurVNy3Qo
ye30uaENTd1KTi2JhPxyNutjV2NFaXsgTNKB5lK9tJLLyr5x1OeWrIjnTVJcK7mhyCW72Fil
RVKxeefJNrbtTDT4diYsRe0z70dtfGYwi2RAEm5b7UfOj82tm6eHlvLEeapzuaI957ZIJuBl
gM4pTefcynGfv+dXGCXispx2WSvuXdu8BEn6K6f8lk5tdzJYkhnObZP1/Nj3xHPwzGNa+Sog
s/Zr7b7Z3nVVh6qmhiXLeVvlkNdkzlZiYLWrbqpApuj7RLfd5Dy/acdUJWViard6qGJL9HmW
JnV9bG7H1LflgTDpfshB1wvavEn22sPOR5AlmSP9rHDmvp8P8kI+nxX5WC2UIh2V25Hlo+fZ
MrZt2+/VEs/L1vHg3PIeHhmmXbofb0eC/RZaaKGFFlpooYUWWmihhRZaaKGFFlpooYUWWmih
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
--------------4B194FF8F3EA3786FF9EAE1F
Content-Type: application/x-compressed-tar;
 name="brin-stress-test.tgz"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
 filename="brin-stress-test.tgz"

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
4sSJE/vk/y10LU4AkAEA
--------------4B194FF8F3EA3786FF9EAE1F
Content-Type: application/x-compressed-tar;
 name="brin-bench.tgz"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
 filename="brin-bench.tgz"

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
--------------4B194FF8F3EA3786FF9EAE1F--





^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/9] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 4e0c9be58c..4099e72001 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8191,7 +8191,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------0E72B707603BED22B4040825--





^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/9] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 1487710d59..33841e14f2 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8191,7 +8191,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------22A4B241170149838D4D1F8F
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210215.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210215.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 58fe109d2d..8a1a9da78f 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -389,6 +389,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -410,6 +413,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -470,7 +528,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -480,51 +538,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index d7b55f57ea..871e024e00 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8143,7 +8143,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8159,7 +8159,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------CF71AF65F7C337C37C24B045
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210112.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210112.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/6] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 58fe109d2d..8a1a9da78f 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -389,6 +389,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -410,6 +413,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -470,7 +528,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -480,51 +538,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index d7b55f57ea..871e024e00 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8143,7 +8143,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8159,7 +8159,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------D21F32E0F9E7408E9BE1AF2E
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210114.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210114.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/6] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index d27336adcd..f3ead7d53d 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8145,7 +8145,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8161,7 +8161,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------310A2AE1CC4C2E2E77559E3D
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-suppo-20210114-2.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-suppo-20210114-2.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index b5f52d4e4a..2ef11245a8 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8183,7 +8183,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8199,7 +8199,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------FA974B75A0C3E9CA18CE7207
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210122.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210122.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/6] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 158 ++++++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 140 ++++++++++++++------
 src/backend/access/brin/brin_minmax.c    |  92 ++++++++++---
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 303 insertions(+), 95 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..963b7079cf 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,78 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of
+					 * multiple scan keys. We can determine that based on the
+					 * number of arguments - functions with extra parameter
+					 * (number of scan keys) do support this, otherwise we
+					 * have to simply pass the scan keys one by one, as
+					 * before.
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same
+						 * for all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet
+						 * the criteria for a single one of them is enough to
+						 * discard the range as a whole, so break out of the
+						 * loop as soon as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+
+							/* mismatching key, no need to look further  */
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..a260074c91 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -251,6 +253,10 @@ brin_inclusion_add_value(PG_FUNCTION_ARGS)
 /*
  * BRIN inclusion consistent function
  *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
+ *
  * All of the strategies are optional.
  */
 Datum
@@ -258,24 +264,31 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/* Handle IS NULL/IS NOT NULL tests */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -284,7 +297,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -293,7 +311,14 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
@@ -301,10 +326,45 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all regular scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* Skip IS NULL/IS NOT NULL keys (already handled above). */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
+	/* This should be called only for regular keys, not for IS [NOT] NULL. */
+	Assert(!(key->sk_flags & SK_ISNULL));
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +384,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +444,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +464,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +483,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +518,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +528,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..e116084a02 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -140,29 +142,41 @@ brin_minmax_add_value(PG_FUNCTION_ARGS)
  * Given an index tuple corresponding to a certain page range and a scan key,
  * return whether the scan key is consistent with the index tuple's min/max
  * values.  Return true if so, false otherwise.
+ *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
  */
 Datum
 brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
 	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -171,7 +185,12 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -180,13 +199,52 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
+	}
+
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
+
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +287,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 1487710d59..33841e14f2 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8191,7 +8191,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------6A37408A2C42B5B56C3B3D49
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210303.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210303.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c          | 158 +++++++++++++++++++-----
 src/backend/access/brin/brin_validate.c |   4 +-
 2 files changed, 126 insertions(+), 36 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..963b7079cf 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,78 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of
+					 * multiple scan keys. We can determine that based on the
+					 * number of arguments - functions with extra parameter
+					 * (number of scan keys) do support this, otherwise we
+					 * have to simply pass the scan keys one by one, as
+					 * before.
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same
+						 * for all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet
+						 * the criteria for a single one of them is enough to
+						 * discard the range as a whole, so break out of the
+						 * loop as soon as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+
+							/* mismatching key, no need to look further  */
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-- 
2.26.2


--------------AC3FFB734F56C5F52D422EFC
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Process-all-scan-keys-in-existing-BRIN-opcl-20210305.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Process-all-scan-keys-in-existing-BRIN-opcl-20210305.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c          | 158 +++++++++++++++++++-----
 src/backend/access/brin/brin_validate.c |   4 +-
 2 files changed, 126 insertions(+), 36 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..f9a0476024 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,78 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any scan keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of
+					 * multiple scan keys. We can determine that based on the
+					 * number of arguments - functions with extra parameter
+					 * (number of scan keys) do support this, otherwise we
+					 * have to simply pass the scan keys one by one, as
+					 * before.
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same
+						 * for all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet
+						 * the criteria for a single one of them is enough to
+						 * discard the range as a whole, so break out of the
+						 * loop as soon as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+
+							/* mismatching key, no need to look further  */
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-- 
2.26.2


--------------82D677E9F94AC7574E460205
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Process-all-scan-keys-in-existing-BRIN-opcl-20210308.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Process-all-scan-keys-in-existing-BRIN-opcl-20210308.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c          | 158 +++++++++++++++++++-----
 src/backend/access/brin/brin_validate.c |   4 +-
 2 files changed, 126 insertions(+), 36 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..f9a0476024 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,78 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any scan keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of
+					 * multiple scan keys. We can determine that based on the
+					 * number of arguments - functions with extra parameter
+					 * (number of scan keys) do support this, otherwise we
+					 * have to simply pass the scan keys one by one, as
+					 * before.
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same
+						 * for all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet
+						 * the criteria for a single one of them is enough to
+						 * discard the range as a whole, so break out of the
+						 * loop as soon as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+
+							/* mismatching key, no need to look further  */
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-- 
2.26.2


--------------556A1DC61262AF15641DB204
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Process-all-scan-keys-in-existing-BRIN-opc-20210308b.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Process-all-scan-keys-in-existing-BRIN-opc-20210308b.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow future opclases to benefit from seeing all keys at once.

This does break existing BRIN opclasses, because the signature of the
consistent function changed. We might support both variants (with 3 and
4 parameters), but that seems pointless - the changes to NULL handling
likely require updates too. So better to make the failure clear. Also,
we're not aware of any out-of-core opclasses - there may be some, but
probably not many.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 doc/src/sgml/brin.sgml                   |   8 +-
 src/backend/access/brin/brin.c           | 118 +++++++++++++------
 src/backend/access/brin/brin_inclusion.c | 140 ++++++++++++++++-------
 src/backend/access/brin/brin_minmax.c    |  92 ++++++++++++---
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 6 files changed, 269 insertions(+), 97 deletions(-)

diff --git a/doc/src/sgml/brin.sgml b/doc/src/sgml/brin.sgml
index 06880c0f7b..078f51bb55 100644
--- a/doc/src/sgml/brin.sgml
+++ b/doc/src/sgml/brin.sgml
@@ -464,12 +464,14 @@ typedef struct BrinOpcInfo
 
    <varlistentry>
     <term><function>bool consistent(BrinDesc *bdesc, BrinValues *column,
-       ScanKey key)</function></term>
+       ScanKey *keys, int nkeys)</function></term>
     <listitem>
      <para>
-      Returns whether the ScanKey is consistent with the given indexed
-      values for a range.
+      Returns whether all the ScanKey entries are consistent with the given
+      indexed values for a range.
       The attribute number to use is passed as part of the scan key.
+      Multiple scan keys for the same attribute may be passed at once, the
+      number of entries is determined by the <literal>nkeys</literal> parameter.
      </para>
     </listitem>
    </varlistentry>
diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..743f2a925a 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,40 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
+					Oid			collation;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
-
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
-
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					/* skip attributes without any scan keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
+
+					bval = &dtup->bt_columns[attno - 1];
+
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * XXX We simply use the collation from the first key (it
+					 * has to be the same for all keys for the same attribue).
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
+					collation = keys[attno - 1][0]->sk_collation;
+
+					/* Check all keys at once */
+					add = FunctionCall4Coll(&consistentFn[attno - 1],
+											collation,
 											PointerGetDatum(bdesc),
 											PointerGetDatum(bval),
-											PointerGetDatum(key));
+											PointerGetDatum(keys[attno - 1]),
+											Int32GetDatum(nkeys[attno - 1]));
 					addrange = DatumGetBool(add);
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..a260074c91 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -251,6 +253,10 @@ brin_inclusion_add_value(PG_FUNCTION_ARGS)
 /*
  * BRIN inclusion consistent function
  *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
+ *
  * All of the strategies are optional.
  */
 Datum
@@ -258,24 +264,31 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/* Handle IS NULL/IS NOT NULL tests */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -284,7 +297,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -293,7 +311,14 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
@@ -301,10 +326,45 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all regular scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* Skip IS NULL/IS NOT NULL keys (already handled above). */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
+	/* This should be called only for regular keys, not for IS [NOT] NULL. */
+	Assert(!(key->sk_flags & SK_ISNULL));
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +384,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +444,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +464,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +483,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +518,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +528,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..e116084a02 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -140,29 +142,41 @@ brin_minmax_add_value(PG_FUNCTION_ARGS)
  * Given an index tuple corresponding to a certain page range and a scan key,
  * return whether the scan key is consistent with the index tuple's min/max
  * values.  Return true if so, false otherwise.
+ *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
  */
 Datum
 brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
 	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -171,7 +185,12 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -180,13 +199,52 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
+	}
+
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
+
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +287,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..2c4f9a3eff 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											4, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index c7619f8cd3..cd1eda38ab 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8223,7 +8223,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------D524CD37E77B36A2883A7617
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Move-IS-NOT-NULL-handling-from-BRIN-support-20210311.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Move-IS-NOT-NULL-handling-from-BRIN-support-20210311.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/9] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 4e0c9be58c..4099e72001 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8191,7 +8191,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------4B194FF8F3EA3786FF9EAE1F
Content-Type: application/vnd.oasis.opendocument.spreadsheet;
 name="brin-bench.ods"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
 filename="brin-bench.ods"

UEsDBBQAAAgAAOO7Q1KFbDmKLgAAAC4AAAAIAAAAbWltZXR5cGVhcHBsaWNhdGlvbi92bmQu
b2FzaXMub3BlbmRvY3VtZW50LnNwcmVhZHNoZWV0UEsDBBQAAAgAAOO7Q1IAAAAAAAAAAAAA
AAAcAAAAQ29uZmlndXJhdGlvbnMyL2FjY2VsZXJhdG9yL1BLAwQUAAAIAADju0NSAAAAAAAA
AAAAAAAAHwAAAENvbmZpZ3VyYXRpb25zMi9pbWFnZXMvQml0bWFwcy9QSwMEFAAACAAA47tD
UgAAAAAAAAAAAAAAABgAAABDb25maWd1cmF0aW9uczIvdG9vbGJhci9QSwMEFAAACAAA47tD
UgAAAAAAAAAAAAAAABgAAABDb25maWd1cmF0aW9uczIvZmxvYXRlci9QSwMEFAAACAAA47tD
UgAAAAAAAAAAAAAAABoAAABDb25maWd1cmF0aW9uczIvcG9wdXBtZW51L1BLAwQUAAAIAADj
u0NSAAAAAAAAAAAAAAAAGAAAAENvbmZpZ3VyYXRpb25zMi9tZW51YmFyL1BLAwQUAAAIAADj
u0NSAAAAAAAAAAAAAAAAGgAAAENvbmZpZ3VyYXRpb25zMi90b29scGFuZWwvUEsDBBQAAAgA
AOO7Q1IAAAAAAAAAAAAAAAAaAAAAQ29uZmlndXJhdGlvbnMyL3N0YXR1c2Jhci9QSwMEFAAA
CAAA47tDUgAAAAAAAAAAAAAAABwAAABDb25maWd1cmF0aW9uczIvcHJvZ3Jlc3NiYXIvUEsD
BBQACAgIAOO7Q1IAAAAAAAAAAAAAAAAMAAAAbWFuaWZlc3QucmRmzZPNboMwEITvPIVlzthA
LwUFcijKuWqfwDWGWAUv8poS3r6Ok1ZRpKrqn9TjrkYz3460m+1hHMiLsqjBVDRjKSXKSGi1
6Ss6uy65pds62ti2Kx+aHfFqg6WfKrp3bio5X5aFLTcMbM+zoih4mvM8T7wiwdU4cUgMxrSO
CAkejUJp9eR8GjnO4glmV1F066CQefcgPYvdOqmgsgphtlK9h7YgkYFAjQlMyoR0gxy6TkvF
M5bzUTnBoe3ix2C904OiPGDwK47P2N6IDKblXuC9sO5cg998lWh67mN6ddPF8d8jlGCcMu5P
6rs7ef/n/i7P/xnir7R2RGxAzqNn+pDntPIfVUevUEsHCLT3aNIFAQAAgwMAAFBLAwQUAAgI
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
qj3ilyQOPhr0ABLtL3rhZyov0EILLbTQQgsttND+W1rqv9n/cfyPtLu9/1v//Op6vYEY/1mt
W6p3rm9s+rFGaz8x2MF6O6wN/SU0Y2o3tvDifH1Jv4qU7vqardljWAZb3pyj1Tq6spysn/fd
2kTWub1a2+VJvKrVtXjeoiYdYprGsV9fxoqz3RtNUinHrl0haYvWpK6ELiWP4mOcD1bNUlgn
6uNKr69UXetjCoGnpsaut8D1spZC5LSaHJ0d1czXz8RDc7d5Xl9JkXeLGk6noLyv069jXdNk
vHUxiHZKk/clm/mSVvMxB7N+Wwrb+ur8Rl5vV7WKquUlh2kYw5Hzcn1uJ5KV344XmvjGZUpE
Stoq+wVtm/1QsoBjNO341mdqLcsKuza3xemjv4aNbm0aIxcZr6vahaTTlXfDKXC0/hPnbbIh
dLuFtK3JJRedK9LWwkv4dazpvPpsU+lmWzg6OQPk79IYL24UG9bslrl36/rubP6q+62s5Pf9
wHc1PnlNpg9l0CfL+PFzjx2XGxkfGnh7uNz5iO/djLTU957HpfBBL+pD0eqTRd9D7o/6e7y+
FvihAf0zWF0OlqCfvepL4Vohc/xLuiQb8JEHU5ZKK8zje+XvT6sPycePmnz4Ht4L/c7BjvxQ
okqyG1PpV7RJyfVaJ3XoNLfogiEllSAVaYLorhsnctwrZOQlenur3985r7+vxDrOVa7h5t79
g2aV7QOJ5jA3Zp3MfkE78spr5nXxXL0erGVDloocPvFtUd4Zmr3e9SJbgfZzf8nBurVNy3Qo
ye30uaENTd1KTi2JhPxyNutjV2NFaXsgTNKB5lK9tJLLyr5x1OeWrIjnTVJcK7mhyCW72Fil
RVKxeefJNrbtTDT4diYsRe0z70dtfGYwi2RAEm5b7UfOj82tm6eHlvLEeapzuaI957ZIJuBl
gM4pTefcynGfv+dXGCXispx2WSvuXdu8BEn6K6f8lk5tdzJYkhnObZP1/Nj3xHPwzGNa+Sog
s/Zr7b7Z3nVVh6qmhiXLeVvlkNdkzlZiYLWrbqpApuj7RLfd5Dy/acdUJWViard6qGJL9HmW
JnV9bG7H1LflgTDpfshB1wvavEn22sPOR5AlmSP9rHDmvp8P8kI+nxX5WC2UIh2V25Hlo+fZ
MrZt2+/VEs/L1vHg3PIeHhmmXbofb0eC/RZaaKGFFlpooYUWWmihhRZaaKGFFlpooYUWWmih
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
--------------4B194FF8F3EA3786FF9EAE1F
Content-Type: application/x-compressed-tar;
 name="brin-stress-test.tgz"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
 filename="brin-stress-test.tgz"

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
4sSJE/vk/y10LU4AkAEA
--------------4B194FF8F3EA3786FF9EAE1F
Content-Type: application/x-compressed-tar;
 name="brin-bench.tgz"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
 filename="brin-bench.tgz"

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
--------------4B194FF8F3EA3786FF9EAE1F--





^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/9] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 4e0c9be58c..4099e72001 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8191,7 +8191,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------0E72B707603BED22B4040825--





^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/9] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 1487710d59..33841e14f2 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8191,7 +8191,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------22A4B241170149838D4D1F8F
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210215.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210215.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 58fe109d2d..8a1a9da78f 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -389,6 +389,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -410,6 +413,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -470,7 +528,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -480,51 +538,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index d7b55f57ea..871e024e00 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8143,7 +8143,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8159,7 +8159,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------CF71AF65F7C337C37C24B045
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210112.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210112.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/6] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 58fe109d2d..8a1a9da78f 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -389,6 +389,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -410,6 +413,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -470,7 +528,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -480,51 +538,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index d7b55f57ea..871e024e00 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8143,7 +8143,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8159,7 +8159,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------D21F32E0F9E7408E9BE1AF2E
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210114.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210114.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/6] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index d27336adcd..f3ead7d53d 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8145,7 +8145,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8161,7 +8161,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------310A2AE1CC4C2E2E77559E3D
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-suppo-20210114-2.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-suppo-20210114-2.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index b5f52d4e4a..2ef11245a8 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8183,7 +8183,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8199,7 +8199,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------FA974B75A0C3E9CA18CE7207
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210122.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210122.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/6] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 158 ++++++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 140 ++++++++++++++------
 src/backend/access/brin/brin_minmax.c    |  92 ++++++++++---
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 303 insertions(+), 95 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..963b7079cf 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,78 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of
+					 * multiple scan keys. We can determine that based on the
+					 * number of arguments - functions with extra parameter
+					 * (number of scan keys) do support this, otherwise we
+					 * have to simply pass the scan keys one by one, as
+					 * before.
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same
+						 * for all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet
+						 * the criteria for a single one of them is enough to
+						 * discard the range as a whole, so break out of the
+						 * loop as soon as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+
+							/* mismatching key, no need to look further  */
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..a260074c91 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -251,6 +253,10 @@ brin_inclusion_add_value(PG_FUNCTION_ARGS)
 /*
  * BRIN inclusion consistent function
  *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
+ *
  * All of the strategies are optional.
  */
 Datum
@@ -258,24 +264,31 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/* Handle IS NULL/IS NOT NULL tests */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -284,7 +297,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -293,7 +311,14 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
@@ -301,10 +326,45 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all regular scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* Skip IS NULL/IS NOT NULL keys (already handled above). */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
+	/* This should be called only for regular keys, not for IS [NOT] NULL. */
+	Assert(!(key->sk_flags & SK_ISNULL));
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +384,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +444,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +464,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +483,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +518,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +528,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..e116084a02 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -140,29 +142,41 @@ brin_minmax_add_value(PG_FUNCTION_ARGS)
  * Given an index tuple corresponding to a certain page range and a scan key,
  * return whether the scan key is consistent with the index tuple's min/max
  * values.  Return true if so, false otherwise.
+ *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
  */
 Datum
 brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
 	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -171,7 +185,12 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -180,13 +199,52 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
+	}
+
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
+
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +287,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 1487710d59..33841e14f2 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8191,7 +8191,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------6A37408A2C42B5B56C3B3D49
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210303.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210303.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c          | 158 +++++++++++++++++++-----
 src/backend/access/brin/brin_validate.c |   4 +-
 2 files changed, 126 insertions(+), 36 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..963b7079cf 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,78 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of
+					 * multiple scan keys. We can determine that based on the
+					 * number of arguments - functions with extra parameter
+					 * (number of scan keys) do support this, otherwise we
+					 * have to simply pass the scan keys one by one, as
+					 * before.
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same
+						 * for all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet
+						 * the criteria for a single one of them is enough to
+						 * discard the range as a whole, so break out of the
+						 * loop as soon as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+
+							/* mismatching key, no need to look further  */
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-- 
2.26.2


--------------AC3FFB734F56C5F52D422EFC
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Process-all-scan-keys-in-existing-BRIN-opcl-20210305.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Process-all-scan-keys-in-existing-BRIN-opcl-20210305.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c          | 158 +++++++++++++++++++-----
 src/backend/access/brin/brin_validate.c |   4 +-
 2 files changed, 126 insertions(+), 36 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..f9a0476024 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,78 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any scan keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of
+					 * multiple scan keys. We can determine that based on the
+					 * number of arguments - functions with extra parameter
+					 * (number of scan keys) do support this, otherwise we
+					 * have to simply pass the scan keys one by one, as
+					 * before.
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same
+						 * for all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet
+						 * the criteria for a single one of them is enough to
+						 * discard the range as a whole, so break out of the
+						 * loop as soon as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+
+							/* mismatching key, no need to look further  */
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-- 
2.26.2


--------------82D677E9F94AC7574E460205
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Process-all-scan-keys-in-existing-BRIN-opcl-20210308.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Process-all-scan-keys-in-existing-BRIN-opcl-20210308.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c          | 158 +++++++++++++++++++-----
 src/backend/access/brin/brin_validate.c |   4 +-
 2 files changed, 126 insertions(+), 36 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..f9a0476024 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,78 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any scan keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of
+					 * multiple scan keys. We can determine that based on the
+					 * number of arguments - functions with extra parameter
+					 * (number of scan keys) do support this, otherwise we
+					 * have to simply pass the scan keys one by one, as
+					 * before.
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same
+						 * for all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet
+						 * the criteria for a single one of them is enough to
+						 * discard the range as a whole, so break out of the
+						 * loop as soon as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+
+							/* mismatching key, no need to look further  */
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-- 
2.26.2


--------------556A1DC61262AF15641DB204
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Process-all-scan-keys-in-existing-BRIN-opc-20210308b.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Process-all-scan-keys-in-existing-BRIN-opc-20210308b.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow future opclases to benefit from seeing all keys at once.

This does break existing BRIN opclasses, because the signature of the
consistent function changed. We might support both variants (with 3 and
4 parameters), but that seems pointless - the changes to NULL handling
likely require updates too. So better to make the failure clear. Also,
we're not aware of any out-of-core opclasses - there may be some, but
probably not many.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 doc/src/sgml/brin.sgml                   |   8 +-
 src/backend/access/brin/brin.c           | 118 +++++++++++++------
 src/backend/access/brin/brin_inclusion.c | 140 ++++++++++++++++-------
 src/backend/access/brin/brin_minmax.c    |  92 ++++++++++++---
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 6 files changed, 269 insertions(+), 97 deletions(-)

diff --git a/doc/src/sgml/brin.sgml b/doc/src/sgml/brin.sgml
index 06880c0f7b..078f51bb55 100644
--- a/doc/src/sgml/brin.sgml
+++ b/doc/src/sgml/brin.sgml
@@ -464,12 +464,14 @@ typedef struct BrinOpcInfo
 
    <varlistentry>
     <term><function>bool consistent(BrinDesc *bdesc, BrinValues *column,
-       ScanKey key)</function></term>
+       ScanKey *keys, int nkeys)</function></term>
     <listitem>
      <para>
-      Returns whether the ScanKey is consistent with the given indexed
-      values for a range.
+      Returns whether all the ScanKey entries are consistent with the given
+      indexed values for a range.
       The attribute number to use is passed as part of the scan key.
+      Multiple scan keys for the same attribute may be passed at once, the
+      number of entries is determined by the <literal>nkeys</literal> parameter.
      </para>
     </listitem>
    </varlistentry>
diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..743f2a925a 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,40 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
+					Oid			collation;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
-
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
-
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					/* skip attributes without any scan keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
+
+					bval = &dtup->bt_columns[attno - 1];
+
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * XXX We simply use the collation from the first key (it
+					 * has to be the same for all keys for the same attribue).
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
+					collation = keys[attno - 1][0]->sk_collation;
+
+					/* Check all keys at once */
+					add = FunctionCall4Coll(&consistentFn[attno - 1],
+											collation,
 											PointerGetDatum(bdesc),
 											PointerGetDatum(bval),
-											PointerGetDatum(key));
+											PointerGetDatum(keys[attno - 1]),
+											Int32GetDatum(nkeys[attno - 1]));
 					addrange = DatumGetBool(add);
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..a260074c91 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -251,6 +253,10 @@ brin_inclusion_add_value(PG_FUNCTION_ARGS)
 /*
  * BRIN inclusion consistent function
  *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
+ *
  * All of the strategies are optional.
  */
 Datum
@@ -258,24 +264,31 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/* Handle IS NULL/IS NOT NULL tests */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -284,7 +297,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -293,7 +311,14 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
@@ -301,10 +326,45 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all regular scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* Skip IS NULL/IS NOT NULL keys (already handled above). */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
+	/* This should be called only for regular keys, not for IS [NOT] NULL. */
+	Assert(!(key->sk_flags & SK_ISNULL));
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +384,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +444,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +464,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +483,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +518,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +528,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..e116084a02 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -140,29 +142,41 @@ brin_minmax_add_value(PG_FUNCTION_ARGS)
  * Given an index tuple corresponding to a certain page range and a scan key,
  * return whether the scan key is consistent with the index tuple's min/max
  * values.  Return true if so, false otherwise.
+ *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
  */
 Datum
 brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
 	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -171,7 +185,12 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -180,13 +199,52 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
+	}
+
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
+
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +287,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..2c4f9a3eff 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											4, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index c7619f8cd3..cd1eda38ab 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8223,7 +8223,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------D524CD37E77B36A2883A7617
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Move-IS-NOT-NULL-handling-from-BRIN-support-20210311.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Move-IS-NOT-NULL-handling-from-BRIN-support-20210311.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/9] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 4e0c9be58c..4099e72001 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8191,7 +8191,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------4B194FF8F3EA3786FF9EAE1F
Content-Type: application/vnd.oasis.opendocument.spreadsheet;
 name="brin-bench.ods"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
 filename="brin-bench.ods"

UEsDBBQAAAgAAOO7Q1KFbDmKLgAAAC4AAAAIAAAAbWltZXR5cGVhcHBsaWNhdGlvbi92bmQu
b2FzaXMub3BlbmRvY3VtZW50LnNwcmVhZHNoZWV0UEsDBBQAAAgAAOO7Q1IAAAAAAAAAAAAA
AAAcAAAAQ29uZmlndXJhdGlvbnMyL2FjY2VsZXJhdG9yL1BLAwQUAAAIAADju0NSAAAAAAAA
AAAAAAAAHwAAAENvbmZpZ3VyYXRpb25zMi9pbWFnZXMvQml0bWFwcy9QSwMEFAAACAAA47tD
UgAAAAAAAAAAAAAAABgAAABDb25maWd1cmF0aW9uczIvdG9vbGJhci9QSwMEFAAACAAA47tD
UgAAAAAAAAAAAAAAABgAAABDb25maWd1cmF0aW9uczIvZmxvYXRlci9QSwMEFAAACAAA47tD
UgAAAAAAAAAAAAAAABoAAABDb25maWd1cmF0aW9uczIvcG9wdXBtZW51L1BLAwQUAAAIAADj
u0NSAAAAAAAAAAAAAAAAGAAAAENvbmZpZ3VyYXRpb25zMi9tZW51YmFyL1BLAwQUAAAIAADj
u0NSAAAAAAAAAAAAAAAAGgAAAENvbmZpZ3VyYXRpb25zMi90b29scGFuZWwvUEsDBBQAAAgA
AOO7Q1IAAAAAAAAAAAAAAAAaAAAAQ29uZmlndXJhdGlvbnMyL3N0YXR1c2Jhci9QSwMEFAAA
CAAA47tDUgAAAAAAAAAAAAAAABwAAABDb25maWd1cmF0aW9uczIvcHJvZ3Jlc3NiYXIvUEsD
BBQACAgIAOO7Q1IAAAAAAAAAAAAAAAAMAAAAbWFuaWZlc3QucmRmzZPNboMwEITvPIVlzthA
LwUFcijKuWqfwDWGWAUv8poS3r6Ok1ZRpKrqn9TjrkYz3460m+1hHMiLsqjBVDRjKSXKSGi1
6Ss6uy65pds62ti2Kx+aHfFqg6WfKrp3bio5X5aFLTcMbM+zoih4mvM8T7wiwdU4cUgMxrSO
CAkejUJp9eR8GjnO4glmV1F066CQefcgPYvdOqmgsgphtlK9h7YgkYFAjQlMyoR0gxy6TkvF
M5bzUTnBoe3ix2C904OiPGDwK47P2N6IDKblXuC9sO5cg998lWh67mN6ddPF8d8jlGCcMu5P
6rs7ef/n/i7P/xnir7R2RGxAzqNn+pDntPIfVUevUEsHCLT3aNIFAQAAgwMAAFBLAwQUAAgI
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
qj3ilyQOPhr0ABLtL3rhZyov0EILLbTQQgsttND+W1rqv9n/cfyPtLu9/1v//Op6vYEY/1mt
W6p3rm9s+rFGaz8x2MF6O6wN/SU0Y2o3tvDifH1Jv4qU7vqardljWAZb3pyj1Tq6spysn/fd
2kTWub1a2+VJvKrVtXjeoiYdYprGsV9fxoqz3RtNUinHrl0haYvWpK6ELiWP4mOcD1bNUlgn
6uNKr69UXetjCoGnpsaut8D1spZC5LSaHJ0d1czXz8RDc7d5Xl9JkXeLGk6noLyv069jXdNk
vHUxiHZKk/clm/mSVvMxB7N+Wwrb+ur8Rl5vV7WKquUlh2kYw5Hzcn1uJ5KV344XmvjGZUpE
Stoq+wVtm/1QsoBjNO341mdqLcsKuza3xemjv4aNbm0aIxcZr6vahaTTlXfDKXC0/hPnbbIh
dLuFtK3JJRedK9LWwkv4dazpvPpsU+lmWzg6OQPk79IYL24UG9bslrl36/rubP6q+62s5Pf9
wHc1PnlNpg9l0CfL+PFzjx2XGxkfGnh7uNz5iO/djLTU957HpfBBL+pD0eqTRd9D7o/6e7y+
FvihAf0zWF0OlqCfvepL4Vohc/xLuiQb8JEHU5ZKK8zje+XvT6sPycePmnz4Ht4L/c7BjvxQ
okqyG1PpV7RJyfVaJ3XoNLfogiEllSAVaYLorhsnctwrZOQlenur3985r7+vxDrOVa7h5t79
g2aV7QOJ5jA3Zp3MfkE78spr5nXxXL0erGVDloocPvFtUd4Zmr3e9SJbgfZzf8nBurVNy3Qo
ye30uaENTd1KTi2JhPxyNutjV2NFaXsgTNKB5lK9tJLLyr5x1OeWrIjnTVJcK7mhyCW72Fil
RVKxeefJNrbtTDT4diYsRe0z70dtfGYwi2RAEm5b7UfOj82tm6eHlvLEeapzuaI957ZIJuBl
gM4pTefcynGfv+dXGCXispx2WSvuXdu8BEn6K6f8lk5tdzJYkhnObZP1/Nj3xHPwzGNa+Sog
s/Zr7b7Z3nVVh6qmhiXLeVvlkNdkzlZiYLWrbqpApuj7RLfd5Dy/acdUJWViard6qGJL9HmW
JnV9bG7H1LflgTDpfshB1wvavEn22sPOR5AlmSP9rHDmvp8P8kI+nxX5WC2UIh2V25Hlo+fZ
MrZt2+/VEs/L1vHg3PIeHhmmXbofb0eC/RZaaKGFFlpooYUWWmihhRZaaKGFFlpooYUWWmih
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
--------------4B194FF8F3EA3786FF9EAE1F
Content-Type: application/x-compressed-tar;
 name="brin-stress-test.tgz"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
 filename="brin-stress-test.tgz"

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
4sSJE/vk/y10LU4AkAEA
--------------4B194FF8F3EA3786FF9EAE1F
Content-Type: application/x-compressed-tar;
 name="brin-bench.tgz"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
 filename="brin-bench.tgz"

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
--------------4B194FF8F3EA3786FF9EAE1F--





^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/9] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 4e0c9be58c..4099e72001 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8191,7 +8191,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------0E72B707603BED22B4040825--





^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/9] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 1487710d59..33841e14f2 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8191,7 +8191,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------22A4B241170149838D4D1F8F
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210215.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210215.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 58fe109d2d..8a1a9da78f 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -389,6 +389,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -410,6 +413,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -470,7 +528,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -480,51 +538,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index d7b55f57ea..871e024e00 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8143,7 +8143,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8159,7 +8159,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------CF71AF65F7C337C37C24B045
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210112.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210112.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/6] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 58fe109d2d..8a1a9da78f 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -389,6 +389,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -410,6 +413,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -470,7 +528,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -480,51 +538,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index d7b55f57ea..871e024e00 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8143,7 +8143,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8159,7 +8159,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------D21F32E0F9E7408E9BE1AF2E
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210114.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210114.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/6] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index d27336adcd..f3ead7d53d 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8145,7 +8145,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8161,7 +8161,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------310A2AE1CC4C2E2E77559E3D
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-suppo-20210114-2.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-suppo-20210114-2.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index b5f52d4e4a..2ef11245a8 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8183,7 +8183,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8199,7 +8199,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------FA974B75A0C3E9CA18CE7207
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210122.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210122.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/6] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 158 ++++++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 140 ++++++++++++++------
 src/backend/access/brin/brin_minmax.c    |  92 ++++++++++---
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 303 insertions(+), 95 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..963b7079cf 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,78 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of
+					 * multiple scan keys. We can determine that based on the
+					 * number of arguments - functions with extra parameter
+					 * (number of scan keys) do support this, otherwise we
+					 * have to simply pass the scan keys one by one, as
+					 * before.
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same
+						 * for all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet
+						 * the criteria for a single one of them is enough to
+						 * discard the range as a whole, so break out of the
+						 * loop as soon as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+
+							/* mismatching key, no need to look further  */
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..a260074c91 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -251,6 +253,10 @@ brin_inclusion_add_value(PG_FUNCTION_ARGS)
 /*
  * BRIN inclusion consistent function
  *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
+ *
  * All of the strategies are optional.
  */
 Datum
@@ -258,24 +264,31 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/* Handle IS NULL/IS NOT NULL tests */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -284,7 +297,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -293,7 +311,14 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
@@ -301,10 +326,45 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all regular scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* Skip IS NULL/IS NOT NULL keys (already handled above). */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
+	/* This should be called only for regular keys, not for IS [NOT] NULL. */
+	Assert(!(key->sk_flags & SK_ISNULL));
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +384,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +444,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +464,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +483,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +518,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +528,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..e116084a02 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -140,29 +142,41 @@ brin_minmax_add_value(PG_FUNCTION_ARGS)
  * Given an index tuple corresponding to a certain page range and a scan key,
  * return whether the scan key is consistent with the index tuple's min/max
  * values.  Return true if so, false otherwise.
+ *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
  */
 Datum
 brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
 	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -171,7 +185,12 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -180,13 +199,52 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
+	}
+
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
+
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +287,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 1487710d59..33841e14f2 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8191,7 +8191,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------6A37408A2C42B5B56C3B3D49
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210303.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210303.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c          | 158 +++++++++++++++++++-----
 src/backend/access/brin/brin_validate.c |   4 +-
 2 files changed, 126 insertions(+), 36 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..963b7079cf 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,78 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of
+					 * multiple scan keys. We can determine that based on the
+					 * number of arguments - functions with extra parameter
+					 * (number of scan keys) do support this, otherwise we
+					 * have to simply pass the scan keys one by one, as
+					 * before.
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same
+						 * for all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet
+						 * the criteria for a single one of them is enough to
+						 * discard the range as a whole, so break out of the
+						 * loop as soon as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+
+							/* mismatching key, no need to look further  */
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-- 
2.26.2


--------------AC3FFB734F56C5F52D422EFC
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Process-all-scan-keys-in-existing-BRIN-opcl-20210305.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Process-all-scan-keys-in-existing-BRIN-opcl-20210305.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c          | 158 +++++++++++++++++++-----
 src/backend/access/brin/brin_validate.c |   4 +-
 2 files changed, 126 insertions(+), 36 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..f9a0476024 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,78 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any scan keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of
+					 * multiple scan keys. We can determine that based on the
+					 * number of arguments - functions with extra parameter
+					 * (number of scan keys) do support this, otherwise we
+					 * have to simply pass the scan keys one by one, as
+					 * before.
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same
+						 * for all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet
+						 * the criteria for a single one of them is enough to
+						 * discard the range as a whole, so break out of the
+						 * loop as soon as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+
+							/* mismatching key, no need to look further  */
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-- 
2.26.2


--------------82D677E9F94AC7574E460205
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Process-all-scan-keys-in-existing-BRIN-opcl-20210308.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Process-all-scan-keys-in-existing-BRIN-opcl-20210308.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c          | 158 +++++++++++++++++++-----
 src/backend/access/brin/brin_validate.c |   4 +-
 2 files changed, 126 insertions(+), 36 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..f9a0476024 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,78 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any scan keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of
+					 * multiple scan keys. We can determine that based on the
+					 * number of arguments - functions with extra parameter
+					 * (number of scan keys) do support this, otherwise we
+					 * have to simply pass the scan keys one by one, as
+					 * before.
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same
+						 * for all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet
+						 * the criteria for a single one of them is enough to
+						 * discard the range as a whole, so break out of the
+						 * loop as soon as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+
+							/* mismatching key, no need to look further  */
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-- 
2.26.2


--------------556A1DC61262AF15641DB204
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Process-all-scan-keys-in-existing-BRIN-opc-20210308b.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Process-all-scan-keys-in-existing-BRIN-opc-20210308b.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow future opclases to benefit from seeing all keys at once.

This does break existing BRIN opclasses, because the signature of the
consistent function changed. We might support both variants (with 3 and
4 parameters), but that seems pointless - the changes to NULL handling
likely require updates too. So better to make the failure clear. Also,
we're not aware of any out-of-core opclasses - there may be some, but
probably not many.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 doc/src/sgml/brin.sgml                   |   8 +-
 src/backend/access/brin/brin.c           | 118 +++++++++++++------
 src/backend/access/brin/brin_inclusion.c | 140 ++++++++++++++++-------
 src/backend/access/brin/brin_minmax.c    |  92 ++++++++++++---
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 6 files changed, 269 insertions(+), 97 deletions(-)

diff --git a/doc/src/sgml/brin.sgml b/doc/src/sgml/brin.sgml
index 06880c0f7b..078f51bb55 100644
--- a/doc/src/sgml/brin.sgml
+++ b/doc/src/sgml/brin.sgml
@@ -464,12 +464,14 @@ typedef struct BrinOpcInfo
 
    <varlistentry>
     <term><function>bool consistent(BrinDesc *bdesc, BrinValues *column,
-       ScanKey key)</function></term>
+       ScanKey *keys, int nkeys)</function></term>
     <listitem>
      <para>
-      Returns whether the ScanKey is consistent with the given indexed
-      values for a range.
+      Returns whether all the ScanKey entries are consistent with the given
+      indexed values for a range.
       The attribute number to use is passed as part of the scan key.
+      Multiple scan keys for the same attribute may be passed at once, the
+      number of entries is determined by the <literal>nkeys</literal> parameter.
      </para>
     </listitem>
    </varlistentry>
diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..743f2a925a 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,40 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
+					Oid			collation;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
-
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
-
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					/* skip attributes without any scan keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
+
+					bval = &dtup->bt_columns[attno - 1];
+
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * XXX We simply use the collation from the first key (it
+					 * has to be the same for all keys for the same attribue).
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
+					collation = keys[attno - 1][0]->sk_collation;
+
+					/* Check all keys at once */
+					add = FunctionCall4Coll(&consistentFn[attno - 1],
+											collation,
 											PointerGetDatum(bdesc),
 											PointerGetDatum(bval),
-											PointerGetDatum(key));
+											PointerGetDatum(keys[attno - 1]),
+											Int32GetDatum(nkeys[attno - 1]));
 					addrange = DatumGetBool(add);
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..a260074c91 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -251,6 +253,10 @@ brin_inclusion_add_value(PG_FUNCTION_ARGS)
 /*
  * BRIN inclusion consistent function
  *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
+ *
  * All of the strategies are optional.
  */
 Datum
@@ -258,24 +264,31 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/* Handle IS NULL/IS NOT NULL tests */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -284,7 +297,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -293,7 +311,14 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
@@ -301,10 +326,45 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all regular scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* Skip IS NULL/IS NOT NULL keys (already handled above). */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
+	/* This should be called only for regular keys, not for IS [NOT] NULL. */
+	Assert(!(key->sk_flags & SK_ISNULL));
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +384,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +444,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +464,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +483,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +518,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +528,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..e116084a02 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -140,29 +142,41 @@ brin_minmax_add_value(PG_FUNCTION_ARGS)
  * Given an index tuple corresponding to a certain page range and a scan key,
  * return whether the scan key is consistent with the index tuple's min/max
  * values.  Return true if so, false otherwise.
+ *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
  */
 Datum
 brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
 	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -171,7 +185,12 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -180,13 +199,52 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
+	}
+
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
+
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +287,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..2c4f9a3eff 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											4, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index c7619f8cd3..cd1eda38ab 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8223,7 +8223,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------D524CD37E77B36A2883A7617
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Move-IS-NOT-NULL-handling-from-BRIN-support-20210311.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Move-IS-NOT-NULL-handling-from-BRIN-support-20210311.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/9] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 4e0c9be58c..4099e72001 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8191,7 +8191,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------4B194FF8F3EA3786FF9EAE1F
Content-Type: application/vnd.oasis.opendocument.spreadsheet;
 name="brin-bench.ods"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
 filename="brin-bench.ods"

UEsDBBQAAAgAAOO7Q1KFbDmKLgAAAC4AAAAIAAAAbWltZXR5cGVhcHBsaWNhdGlvbi92bmQu
b2FzaXMub3BlbmRvY3VtZW50LnNwcmVhZHNoZWV0UEsDBBQAAAgAAOO7Q1IAAAAAAAAAAAAA
AAAcAAAAQ29uZmlndXJhdGlvbnMyL2FjY2VsZXJhdG9yL1BLAwQUAAAIAADju0NSAAAAAAAA
AAAAAAAAHwAAAENvbmZpZ3VyYXRpb25zMi9pbWFnZXMvQml0bWFwcy9QSwMEFAAACAAA47tD
UgAAAAAAAAAAAAAAABgAAABDb25maWd1cmF0aW9uczIvdG9vbGJhci9QSwMEFAAACAAA47tD
UgAAAAAAAAAAAAAAABgAAABDb25maWd1cmF0aW9uczIvZmxvYXRlci9QSwMEFAAACAAA47tD
UgAAAAAAAAAAAAAAABoAAABDb25maWd1cmF0aW9uczIvcG9wdXBtZW51L1BLAwQUAAAIAADj
u0NSAAAAAAAAAAAAAAAAGAAAAENvbmZpZ3VyYXRpb25zMi9tZW51YmFyL1BLAwQUAAAIAADj
u0NSAAAAAAAAAAAAAAAAGgAAAENvbmZpZ3VyYXRpb25zMi90b29scGFuZWwvUEsDBBQAAAgA
AOO7Q1IAAAAAAAAAAAAAAAAaAAAAQ29uZmlndXJhdGlvbnMyL3N0YXR1c2Jhci9QSwMEFAAA
CAAA47tDUgAAAAAAAAAAAAAAABwAAABDb25maWd1cmF0aW9uczIvcHJvZ3Jlc3NiYXIvUEsD
BBQACAgIAOO7Q1IAAAAAAAAAAAAAAAAMAAAAbWFuaWZlc3QucmRmzZPNboMwEITvPIVlzthA
LwUFcijKuWqfwDWGWAUv8poS3r6Ok1ZRpKrqn9TjrkYz3460m+1hHMiLsqjBVDRjKSXKSGi1
6Ss6uy65pds62ti2Kx+aHfFqg6WfKrp3bio5X5aFLTcMbM+zoih4mvM8T7wiwdU4cUgMxrSO
CAkejUJp9eR8GjnO4glmV1F066CQefcgPYvdOqmgsgphtlK9h7YgkYFAjQlMyoR0gxy6TkvF
M5bzUTnBoe3ix2C904OiPGDwK47P2N6IDKblXuC9sO5cg998lWh67mN6ddPF8d8jlGCcMu5P
6rs7ef/n/i7P/xnir7R2RGxAzqNn+pDntPIfVUevUEsHCLT3aNIFAQAAgwMAAFBLAwQUAAgI
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
qj3ilyQOPhr0ABLtL3rhZyov0EILLbTQQgsttND+W1rqv9n/cfyPtLu9/1v//Op6vYEY/1mt
W6p3rm9s+rFGaz8x2MF6O6wN/SU0Y2o3tvDifH1Jv4qU7vqardljWAZb3pyj1Tq6spysn/fd
2kTWub1a2+VJvKrVtXjeoiYdYprGsV9fxoqz3RtNUinHrl0haYvWpK6ELiWP4mOcD1bNUlgn
6uNKr69UXetjCoGnpsaut8D1spZC5LSaHJ0d1czXz8RDc7d5Xl9JkXeLGk6noLyv069jXdNk
vHUxiHZKk/clm/mSVvMxB7N+Wwrb+ur8Rl5vV7WKquUlh2kYw5Hzcn1uJ5KV344XmvjGZUpE
Stoq+wVtm/1QsoBjNO341mdqLcsKuza3xemjv4aNbm0aIxcZr6vahaTTlXfDKXC0/hPnbbIh
dLuFtK3JJRedK9LWwkv4dazpvPpsU+lmWzg6OQPk79IYL24UG9bslrl36/rubP6q+62s5Pf9
wHc1PnlNpg9l0CfL+PFzjx2XGxkfGnh7uNz5iO/djLTU957HpfBBL+pD0eqTRd9D7o/6e7y+
FvihAf0zWF0OlqCfvepL4Vohc/xLuiQb8JEHU5ZKK8zje+XvT6sPycePmnz4Ht4L/c7BjvxQ
okqyG1PpV7RJyfVaJ3XoNLfogiEllSAVaYLorhsnctwrZOQlenur3985r7+vxDrOVa7h5t79
g2aV7QOJ5jA3Zp3MfkE78spr5nXxXL0erGVDloocPvFtUd4Zmr3e9SJbgfZzf8nBurVNy3Qo
ye30uaENTd1KTi2JhPxyNutjV2NFaXsgTNKB5lK9tJLLyr5x1OeWrIjnTVJcK7mhyCW72Fil
RVKxeefJNrbtTDT4diYsRe0z70dtfGYwi2RAEm5b7UfOj82tm6eHlvLEeapzuaI957ZIJuBl
gM4pTefcynGfv+dXGCXispx2WSvuXdu8BEn6K6f8lk5tdzJYkhnObZP1/Nj3xHPwzGNa+Sog
s/Zr7b7Z3nVVh6qmhiXLeVvlkNdkzlZiYLWrbqpApuj7RLfd5Dy/acdUJWViard6qGJL9HmW
JnV9bG7H1LflgTDpfshB1wvavEn22sPOR5AlmSP9rHDmvp8P8kI+nxX5WC2UIh2V25Hlo+fZ
MrZt2+/VEs/L1vHg3PIeHhmmXbofb0eC/RZaaKGFFlpooYUWWmihhRZaaKGFFlpooYUWWmih
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
--------------4B194FF8F3EA3786FF9EAE1F
Content-Type: application/x-compressed-tar;
 name="brin-stress-test.tgz"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
 filename="brin-stress-test.tgz"

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
4sSJE/vk/y10LU4AkAEA
--------------4B194FF8F3EA3786FF9EAE1F
Content-Type: application/x-compressed-tar;
 name="brin-bench.tgz"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
 filename="brin-bench.tgz"

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
--------------4B194FF8F3EA3786FF9EAE1F--





^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/9] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 4e0c9be58c..4099e72001 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8191,7 +8191,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------0E72B707603BED22B4040825--





^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/9] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 1487710d59..33841e14f2 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8191,7 +8191,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------22A4B241170149838D4D1F8F
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210215.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210215.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 58fe109d2d..8a1a9da78f 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -389,6 +389,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -410,6 +413,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -470,7 +528,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -480,51 +538,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index d7b55f57ea..871e024e00 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8143,7 +8143,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8159,7 +8159,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------CF71AF65F7C337C37C24B045
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210112.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210112.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/6] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 58fe109d2d..8a1a9da78f 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -389,6 +389,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -410,6 +413,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -470,7 +528,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -480,51 +538,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index d7b55f57ea..871e024e00 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8143,7 +8143,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8159,7 +8159,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------D21F32E0F9E7408E9BE1AF2E
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210114.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210114.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/6] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index d27336adcd..f3ead7d53d 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8145,7 +8145,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8161,7 +8161,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------310A2AE1CC4C2E2E77559E3D
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-suppo-20210114-2.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-suppo-20210114-2.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index b5f52d4e4a..2ef11245a8 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8183,7 +8183,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8199,7 +8199,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------FA974B75A0C3E9CA18CE7207
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210122.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210122.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/6] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 158 ++++++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 140 ++++++++++++++------
 src/backend/access/brin/brin_minmax.c    |  92 ++++++++++---
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 303 insertions(+), 95 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..963b7079cf 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,78 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of
+					 * multiple scan keys. We can determine that based on the
+					 * number of arguments - functions with extra parameter
+					 * (number of scan keys) do support this, otherwise we
+					 * have to simply pass the scan keys one by one, as
+					 * before.
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same
+						 * for all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet
+						 * the criteria for a single one of them is enough to
+						 * discard the range as a whole, so break out of the
+						 * loop as soon as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+
+							/* mismatching key, no need to look further  */
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..a260074c91 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -251,6 +253,10 @@ brin_inclusion_add_value(PG_FUNCTION_ARGS)
 /*
  * BRIN inclusion consistent function
  *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
+ *
  * All of the strategies are optional.
  */
 Datum
@@ -258,24 +264,31 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/* Handle IS NULL/IS NOT NULL tests */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -284,7 +297,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -293,7 +311,14 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
@@ -301,10 +326,45 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all regular scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* Skip IS NULL/IS NOT NULL keys (already handled above). */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
+	/* This should be called only for regular keys, not for IS [NOT] NULL. */
+	Assert(!(key->sk_flags & SK_ISNULL));
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +384,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +444,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +464,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +483,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +518,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +528,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..e116084a02 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -140,29 +142,41 @@ brin_minmax_add_value(PG_FUNCTION_ARGS)
  * Given an index tuple corresponding to a certain page range and a scan key,
  * return whether the scan key is consistent with the index tuple's min/max
  * values.  Return true if so, false otherwise.
+ *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
  */
 Datum
 brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
 	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -171,7 +185,12 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -180,13 +199,52 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
+	}
+
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
+
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +287,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 1487710d59..33841e14f2 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8191,7 +8191,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------6A37408A2C42B5B56C3B3D49
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210303.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210303.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c          | 158 +++++++++++++++++++-----
 src/backend/access/brin/brin_validate.c |   4 +-
 2 files changed, 126 insertions(+), 36 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..963b7079cf 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,78 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of
+					 * multiple scan keys. We can determine that based on the
+					 * number of arguments - functions with extra parameter
+					 * (number of scan keys) do support this, otherwise we
+					 * have to simply pass the scan keys one by one, as
+					 * before.
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same
+						 * for all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet
+						 * the criteria for a single one of them is enough to
+						 * discard the range as a whole, so break out of the
+						 * loop as soon as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+
+							/* mismatching key, no need to look further  */
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-- 
2.26.2


--------------AC3FFB734F56C5F52D422EFC
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Process-all-scan-keys-in-existing-BRIN-opcl-20210305.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Process-all-scan-keys-in-existing-BRIN-opcl-20210305.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c          | 158 +++++++++++++++++++-----
 src/backend/access/brin/brin_validate.c |   4 +-
 2 files changed, 126 insertions(+), 36 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..f9a0476024 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,78 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any scan keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of
+					 * multiple scan keys. We can determine that based on the
+					 * number of arguments - functions with extra parameter
+					 * (number of scan keys) do support this, otherwise we
+					 * have to simply pass the scan keys one by one, as
+					 * before.
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same
+						 * for all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet
+						 * the criteria for a single one of them is enough to
+						 * discard the range as a whole, so break out of the
+						 * loop as soon as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+
+							/* mismatching key, no need to look further  */
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-- 
2.26.2


--------------82D677E9F94AC7574E460205
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Process-all-scan-keys-in-existing-BRIN-opcl-20210308.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Process-all-scan-keys-in-existing-BRIN-opcl-20210308.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c          | 158 +++++++++++++++++++-----
 src/backend/access/brin/brin_validate.c |   4 +-
 2 files changed, 126 insertions(+), 36 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..f9a0476024 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,78 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any scan keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of
+					 * multiple scan keys. We can determine that based on the
+					 * number of arguments - functions with extra parameter
+					 * (number of scan keys) do support this, otherwise we
+					 * have to simply pass the scan keys one by one, as
+					 * before.
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same
+						 * for all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet
+						 * the criteria for a single one of them is enough to
+						 * discard the range as a whole, so break out of the
+						 * loop as soon as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+
+							/* mismatching key, no need to look further  */
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-- 
2.26.2


--------------556A1DC61262AF15641DB204
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Process-all-scan-keys-in-existing-BRIN-opc-20210308b.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Process-all-scan-keys-in-existing-BRIN-opc-20210308b.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow future opclases to benefit from seeing all keys at once.

This does break existing BRIN opclasses, because the signature of the
consistent function changed. We might support both variants (with 3 and
4 parameters), but that seems pointless - the changes to NULL handling
likely require updates too. So better to make the failure clear. Also,
we're not aware of any out-of-core opclasses - there may be some, but
probably not many.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 doc/src/sgml/brin.sgml                   |   8 +-
 src/backend/access/brin/brin.c           | 118 +++++++++++++------
 src/backend/access/brin/brin_inclusion.c | 140 ++++++++++++++++-------
 src/backend/access/brin/brin_minmax.c    |  92 ++++++++++++---
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 6 files changed, 269 insertions(+), 97 deletions(-)

diff --git a/doc/src/sgml/brin.sgml b/doc/src/sgml/brin.sgml
index 06880c0f7b..078f51bb55 100644
--- a/doc/src/sgml/brin.sgml
+++ b/doc/src/sgml/brin.sgml
@@ -464,12 +464,14 @@ typedef struct BrinOpcInfo
 
    <varlistentry>
     <term><function>bool consistent(BrinDesc *bdesc, BrinValues *column,
-       ScanKey key)</function></term>
+       ScanKey *keys, int nkeys)</function></term>
     <listitem>
      <para>
-      Returns whether the ScanKey is consistent with the given indexed
-      values for a range.
+      Returns whether all the ScanKey entries are consistent with the given
+      indexed values for a range.
       The attribute number to use is passed as part of the scan key.
+      Multiple scan keys for the same attribute may be passed at once, the
+      number of entries is determined by the <literal>nkeys</literal> parameter.
      </para>
     </listitem>
    </varlistentry>
diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..743f2a925a 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,40 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
+					Oid			collation;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
-
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
-
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					/* skip attributes without any scan keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
+
+					bval = &dtup->bt_columns[attno - 1];
+
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * XXX We simply use the collation from the first key (it
+					 * has to be the same for all keys for the same attribue).
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
+					collation = keys[attno - 1][0]->sk_collation;
+
+					/* Check all keys at once */
+					add = FunctionCall4Coll(&consistentFn[attno - 1],
+											collation,
 											PointerGetDatum(bdesc),
 											PointerGetDatum(bval),
-											PointerGetDatum(key));
+											PointerGetDatum(keys[attno - 1]),
+											Int32GetDatum(nkeys[attno - 1]));
 					addrange = DatumGetBool(add);
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..a260074c91 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -251,6 +253,10 @@ brin_inclusion_add_value(PG_FUNCTION_ARGS)
 /*
  * BRIN inclusion consistent function
  *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
+ *
  * All of the strategies are optional.
  */
 Datum
@@ -258,24 +264,31 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/* Handle IS NULL/IS NOT NULL tests */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -284,7 +297,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -293,7 +311,14 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
@@ -301,10 +326,45 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all regular scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* Skip IS NULL/IS NOT NULL keys (already handled above). */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
+	/* This should be called only for regular keys, not for IS [NOT] NULL. */
+	Assert(!(key->sk_flags & SK_ISNULL));
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +384,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +444,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +464,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +483,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +518,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +528,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..e116084a02 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -140,29 +142,41 @@ brin_minmax_add_value(PG_FUNCTION_ARGS)
  * Given an index tuple corresponding to a certain page range and a scan key,
  * return whether the scan key is consistent with the index tuple's min/max
  * values.  Return true if so, false otherwise.
+ *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
  */
 Datum
 brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
 	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -171,7 +185,12 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -180,13 +199,52 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
+	}
+
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
+
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +287,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..2c4f9a3eff 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											4, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index c7619f8cd3..cd1eda38ab 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8223,7 +8223,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------D524CD37E77B36A2883A7617
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Move-IS-NOT-NULL-handling-from-BRIN-support-20210311.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Move-IS-NOT-NULL-handling-from-BRIN-support-20210311.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/9] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 4e0c9be58c..4099e72001 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8191,7 +8191,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------4B194FF8F3EA3786FF9EAE1F
Content-Type: application/vnd.oasis.opendocument.spreadsheet;
 name="brin-bench.ods"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
 filename="brin-bench.ods"

UEsDBBQAAAgAAOO7Q1KFbDmKLgAAAC4AAAAIAAAAbWltZXR5cGVhcHBsaWNhdGlvbi92bmQu
b2FzaXMub3BlbmRvY3VtZW50LnNwcmVhZHNoZWV0UEsDBBQAAAgAAOO7Q1IAAAAAAAAAAAAA
AAAcAAAAQ29uZmlndXJhdGlvbnMyL2FjY2VsZXJhdG9yL1BLAwQUAAAIAADju0NSAAAAAAAA
AAAAAAAAHwAAAENvbmZpZ3VyYXRpb25zMi9pbWFnZXMvQml0bWFwcy9QSwMEFAAACAAA47tD
UgAAAAAAAAAAAAAAABgAAABDb25maWd1cmF0aW9uczIvdG9vbGJhci9QSwMEFAAACAAA47tD
UgAAAAAAAAAAAAAAABgAAABDb25maWd1cmF0aW9uczIvZmxvYXRlci9QSwMEFAAACAAA47tD
UgAAAAAAAAAAAAAAABoAAABDb25maWd1cmF0aW9uczIvcG9wdXBtZW51L1BLAwQUAAAIAADj
u0NSAAAAAAAAAAAAAAAAGAAAAENvbmZpZ3VyYXRpb25zMi9tZW51YmFyL1BLAwQUAAAIAADj
u0NSAAAAAAAAAAAAAAAAGgAAAENvbmZpZ3VyYXRpb25zMi90b29scGFuZWwvUEsDBBQAAAgA
AOO7Q1IAAAAAAAAAAAAAAAAaAAAAQ29uZmlndXJhdGlvbnMyL3N0YXR1c2Jhci9QSwMEFAAA
CAAA47tDUgAAAAAAAAAAAAAAABwAAABDb25maWd1cmF0aW9uczIvcHJvZ3Jlc3NiYXIvUEsD
BBQACAgIAOO7Q1IAAAAAAAAAAAAAAAAMAAAAbWFuaWZlc3QucmRmzZPNboMwEITvPIVlzthA
LwUFcijKuWqfwDWGWAUv8poS3r6Ok1ZRpKrqn9TjrkYz3460m+1hHMiLsqjBVDRjKSXKSGi1
6Ss6uy65pds62ti2Kx+aHfFqg6WfKrp3bio5X5aFLTcMbM+zoih4mvM8T7wiwdU4cUgMxrSO
CAkejUJp9eR8GjnO4glmV1F066CQefcgPYvdOqmgsgphtlK9h7YgkYFAjQlMyoR0gxy6TkvF
M5bzUTnBoe3ix2C904OiPGDwK47P2N6IDKblXuC9sO5cg998lWh67mN6ddPF8d8jlGCcMu5P
6rs7ef/n/i7P/xnir7R2RGxAzqNn+pDntPIfVUevUEsHCLT3aNIFAQAAgwMAAFBLAwQUAAgI
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
qj3ilyQOPhr0ABLtL3rhZyov0EILLbTQQgsttND+W1rqv9n/cfyPtLu9/1v//Op6vYEY/1mt
W6p3rm9s+rFGaz8x2MF6O6wN/SU0Y2o3tvDifH1Jv4qU7vqardljWAZb3pyj1Tq6spysn/fd
2kTWub1a2+VJvKrVtXjeoiYdYprGsV9fxoqz3RtNUinHrl0haYvWpK6ELiWP4mOcD1bNUlgn
6uNKr69UXetjCoGnpsaut8D1spZC5LSaHJ0d1czXz8RDc7d5Xl9JkXeLGk6noLyv069jXdNk
vHUxiHZKk/clm/mSVvMxB7N+Wwrb+ur8Rl5vV7WKquUlh2kYw5Hzcn1uJ5KV344XmvjGZUpE
Stoq+wVtm/1QsoBjNO341mdqLcsKuza3xemjv4aNbm0aIxcZr6vahaTTlXfDKXC0/hPnbbIh
dLuFtK3JJRedK9LWwkv4dazpvPpsU+lmWzg6OQPk79IYL24UG9bslrl36/rubP6q+62s5Pf9
wHc1PnlNpg9l0CfL+PFzjx2XGxkfGnh7uNz5iO/djLTU957HpfBBL+pD0eqTRd9D7o/6e7y+
FvihAf0zWF0OlqCfvepL4Vohc/xLuiQb8JEHU5ZKK8zje+XvT6sPycePmnz4Ht4L/c7BjvxQ
okqyG1PpV7RJyfVaJ3XoNLfogiEllSAVaYLorhsnctwrZOQlenur3985r7+vxDrOVa7h5t79
g2aV7QOJ5jA3Zp3MfkE78spr5nXxXL0erGVDloocPvFtUd4Zmr3e9SJbgfZzf8nBurVNy3Qo
ye30uaENTd1KTi2JhPxyNutjV2NFaXsgTNKB5lK9tJLLyr5x1OeWrIjnTVJcK7mhyCW72Fil
RVKxeefJNrbtTDT4diYsRe0z70dtfGYwi2RAEm5b7UfOj82tm6eHlvLEeapzuaI957ZIJuBl
gM4pTefcynGfv+dXGCXispx2WSvuXdu8BEn6K6f8lk5tdzJYkhnObZP1/Nj3xHPwzGNa+Sog
s/Zr7b7Z3nVVh6qmhiXLeVvlkNdkzlZiYLWrbqpApuj7RLfd5Dy/acdUJWViard6qGJL9HmW
JnV9bG7H1LflgTDpfshB1wvavEn22sPOR5AlmSP9rHDmvp8P8kI+nxX5WC2UIh2V25Hlo+fZ
MrZt2+/VEs/L1vHg3PIeHhmmXbofb0eC/RZaaKGFFlpooYUWWmihhRZaaKGFFlpooYUWWmih
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
--------------4B194FF8F3EA3786FF9EAE1F
Content-Type: application/x-compressed-tar;
 name="brin-stress-test.tgz"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
 filename="brin-stress-test.tgz"

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
4sSJE/vk/y10LU4AkAEA
--------------4B194FF8F3EA3786FF9EAE1F
Content-Type: application/x-compressed-tar;
 name="brin-bench.tgz"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
 filename="brin-bench.tgz"

H4sIAAAAAAAAA+2d33PqxhmGfWv9FVsfpoYWjiUsMIPjzJyLpDedpJM07UVPBwu0gOaApEjC
dtP0f+9KwjY/LGnF0aJd825mYicSQnpY8ejVh/nGgeN2xtSdzK/G8a+OS6OO4z+YH8P5WUVD
Z+PGNJOfht7f+qnrfVO/vjkzTF3vXfe6va5xpht9s989I3pVO5A3VmFkBYSc+V4YzQIaZq1X
tFzR8eEPV2PHvRpb4VzTfvjpx3/+fNcwtL99+st37Jeu9o9Pf/0l/u1a++mXH36+62maHXi+
PSadjjPt0CcnjEIS0TDSJgG1IsqWJP+l+eGvi+RX8i25sunDlbtaLEj32z8a5Jtvvvvx+/X6
ZLpyJ5HjuSSwXNtbjhy/6Y8erAVx3KhFAhqtAjck8awkVkg+Nz43tDGdOa5G2EgXk0uje/NR
Z/8Yl8NhsuqfSbKRW4269q0WP4osLHe2smaU+At/xnbuVov3QvtAlp7rRZ7rTNrsGSbsAY47
ayfPuHkUnQm5WO/yyl14sxm1SWSNF5REpGklq7cu9o51ZwOOG9Igig/NYw8L6YJOoo0Dd1pk
GnhLMqMuDdgzjdjaDg2bRruRvDItErJ1Cp/lwZqsVktiudbiP7+x/St8wGROJ198j+3WG6tq
4d19snqHrfzp9UHrvfdno8iLrMUooAsrfiFHofMbbV5Gl62Le02begEJ2AGT+5D+SgzSiKfR
/S2xPU07/8BewNlqwU6/cRRQylaz6ZN2vjl14vekj9HSX0+az5GzZC/P8+RJHkAc+4mwCRS/
Dq3bZH6+Lli/yufR3T07eX3yd2dJXzf6O5lTyyYdl+3Z78R6/EIu/+uzhRFpdP93yXb/nE7m
3usM6bAJQl7eIdd7nb42pJGcM6SRnjGkEZJGQBpRcpjxExK240vr6asPchWyZekW2fGSRyea
k6bPJnY48mkwYrOJzfG79e4cmUcskPVhclNZLSJHCJtkx0bplkfJ04w8P2yyt4XVLqt071oy
0oz3uyzT8cJj7yICYCYbjilKSCo96CJEtufS3bf1ZE/X7+VvvQHmOqJNfMu2qV3SFW0Si/Kp
Cme0ydLuNZ3hMNkeDKKQQTrp3IFIMrDAJ6KgQivlgB3LLjaVM4KkR9422h0DDqnbIfEkQQzJ
AQJvVI8TxuBFVZcr1IgiMIm0JkEcKeACrwijCr2UJCbOMh8qGju6MnSd2E4YOS57m01naT0Z
Z+nZTafNdqeFu2WS+4m9SKi5FDOBl4QQhZNK0DpW6ok18mwPyWoxG2JBUUZpzSAJFaOBdESC
hXvKQzumgvaSTN2Vm8JUgxtvkhkHZRwOKLCMGKTwSxlcUplFjphDuHMOxCO1eJB1ONhAQ0LJ
wkYHUFOxAiRdDQhVICWchToQHxV4ShBTGKoUryMGJgXqQagIvQPlICfxwIGAxKKFhw7Bdlwd
yVsbQnVIIfugPsSFBcYRBRWuKQdMMsvIEX9IifwDCUkuIWQgLjpQkmC2MNNB3NSoGKUGkegP
hprxnvxp/T+arVb8JXO4hSenv9IXKT4VEJ0yYMBO1aKEjHgwCQ1Hm8rYNEXdEehtc6AUpKZH
Tj395DKBVYQQhVxK0FIu38iUcJBx1HMTUk4ODhipapiQER+oY2UdCdMO8s57cgoSTy4VGEYQ
U4imFC9xvqm7PRGG4JHOn/3+X/0j9v8y9I3+X+ZN0v/rBv2/jjKk7f81dmalWoCxmTQ0p4Ph
9XBsDbtUHw6M6XQ4pd3u0DamxpXRHex0B2MXqkY6BdEnDNfQwhpJ9E/26jmTB66bK6eJK2ZO
UugThrswqhnk1G/DFGGBT0RBhVbKAUOfMPwFhzQO2fokOGLIPhB4o3qcMAYvKvQJw98CKmkS
xJECLvCKMKrQS0lianwmFn3C4KevmP+7fSEQdt5kAi8JIQonlaCFPmHoE/ZuNIMkVIwG0hEJ
Fu4pD02qbi7SpRrceJPMOCjjcECBZcQghV/K4JLKLHLEHPQJeyfiQdbhYAMNCSULGx1ATcUK
kHQ1IFSBlHAW6kB8VOApQUxhqFK80CcMfcLemXKQk3jgQEBi0cJDh2CTrIOLhGkHN+mksw/q
Q1xYYBxRUOGacsAks4wc8Qd9wt6RhJCBuOhASYLZwkwHcVOjYoQ+YfBXlb0kTjc6vQ0DdqoW
JWTEgwl9wvC9+Yp75NTTTy4TWEUIUcilBC3l8o1MCQcZRz03IeXk4ICRqoYJGfGBQp8w5J13
4RQknlwqMIwgphBNKV7oE4axM9J5sdn/KzIrbP2VjIL+X93e9fVL/y+zZ5zpRq/XRf+vowxR
/b+ye6FEZqnrzkMvNx1cP8p4/bjbRCE63b7lb6GQ7UoxMhW4UswEKc/lIeMozcd/tiHV0g8r
Mg+6B/G1tyAc3GFQ0RCnfnchhwh8IYAntMHNqp4eJvVGCPz1gUSOWH+KGTFimwW8UClJGIGD
Ul0ukDdKwBQymgJxIhsJvCECKPTBD0uNz2YW96s6UkZ5/Tp33M2S2z+vPQkQVvZwwDtVw4Rz
+EDV3o+qpgDzKg4URVTVCJJMLhVIRRBTuKUUL4m6gkiSSnBjTDKjoIySyQMWqZwm/MFJSipz
1BhTCG9OgVhkFQuySj4WaEYUVNimHDAVKzBy1GBQhVHBSajD5AGBh6rHCQPxopKgH1Td9RhU
ZJRWCnJOARcIRhhVeKYkMak6cUiTVnATTTq7oD6TQwRGEcATLuFmJZlFaq7ToFKjvGSQYYrA
QDnisMI8ZZGpUbEp6Nd0pPiz3WkD99ZkFNPWF/ifcObZ4wDtVEYRlikgVEMjppqyy7YSUHxR
ThCnnleycEAXVcOENfhAKZdI6s4kSCUKSQe5ZI8EVFMhR1imkFEtrZPqyydIKKrLAhklCwjU
UT1OGIQX1Yn3REoZbPX/GRy7/0/f2Oj/c6On/X/66P9zjFFD/59BiYunsTM7PFajBZCUl0Z7
Xyk/ONmLordQSHc5NFDgcigTpEQXQoO6L4SyINXTAmhwQJZOdYAuQKcoiVMP0DlEoAwBPGEO
blY1dX6oO0jgI+wSaeL5k7EIE1ssoIZKSUIKHJTq0oHUgQKykFEWCBXZSKAOEUBhEH5YanyK
kKMX0NGSCtoBqaKgjW+LR2TZxQH1VA0T2uEDVX87oNpiDDoCqW8S5JlcKvCKIKbQSyleMvV1
kCab4A6ZZFJBSSWTB0RSOU0ohJOUVPKoN6ygL5DybkFiyccC04iCCuGUA6ZiNUaaegwqMipo
CTWZPCBQUfU4ISFeVDK0Bqq/NoPqjNJWQdop4ALHCKMK1ZQkJldfB4kyC+6mSScY1GpyiEAq
AnhCJ9ysJBNJ/TUbVG2U9wySTBEYWEccVsinLDI1qjdFPYKOFoLQJkh+N21/Af3pJp89DjBP
ZRQhmgJCdbQJqi3BoFOQ4o449dSShQPGqBomxMEHSrlcIkEyQTZRyDtIJ3skYJsKOUI0hYzq
aRZUZ0pBTlHdF0gqWUBgj+pxQiK8qN5Zv6D0mF76/1Td+icZ+f1/2DLdfOn/cxP/f8Psmwb6
/xxjbPX/yejtsz9Xt5r9vDGVHzN8PvceSfxG6VuBtVjQxWhpsROMupY7oaNHL/hCgzBWujMl
/yIXjccLdrJScqFfkH/fkmhO3fUpesESeHIiPW+IbGyIPG+IrfzksMshbepsXCUk57W+/qGv
LxPipX6ytE/6JjG6g/WCZMlDvGRArrubC84/vnTMMtlpk5z5Pmk8bC8abC3aWkajjuM/ZD82
Xd7f3UD61rL+kfy77jmEgYGBgYGBgYGBgaHG+D9xSRWUALgBAA==
--------------4B194FF8F3EA3786FF9EAE1F--





^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/9] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 4e0c9be58c..4099e72001 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8191,7 +8191,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------0E72B707603BED22B4040825--





^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/9] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 1487710d59..33841e14f2 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8191,7 +8191,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------22A4B241170149838D4D1F8F
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210215.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210215.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 58fe109d2d..8a1a9da78f 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -389,6 +389,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -410,6 +413,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -470,7 +528,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -480,51 +538,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index d7b55f57ea..871e024e00 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8143,7 +8143,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8159,7 +8159,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------CF71AF65F7C337C37C24B045
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210112.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210112.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/6] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 58fe109d2d..8a1a9da78f 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -389,6 +389,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -410,6 +413,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -470,7 +528,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -480,51 +538,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index d7b55f57ea..871e024e00 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8143,7 +8143,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8159,7 +8159,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------D21F32E0F9E7408E9BE1AF2E
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210114.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210114.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/6] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index d27336adcd..f3ead7d53d 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8145,7 +8145,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8161,7 +8161,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------310A2AE1CC4C2E2E77559E3D
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-suppo-20210114-2.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-suppo-20210114-2.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index b5f52d4e4a..2ef11245a8 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8183,7 +8183,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8199,7 +8199,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------FA974B75A0C3E9CA18CE7207
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210122.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210122.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/6] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 158 ++++++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 140 ++++++++++++++------
 src/backend/access/brin/brin_minmax.c    |  92 ++++++++++---
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 303 insertions(+), 95 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..963b7079cf 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,78 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of
+					 * multiple scan keys. We can determine that based on the
+					 * number of arguments - functions with extra parameter
+					 * (number of scan keys) do support this, otherwise we
+					 * have to simply pass the scan keys one by one, as
+					 * before.
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same
+						 * for all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet
+						 * the criteria for a single one of them is enough to
+						 * discard the range as a whole, so break out of the
+						 * loop as soon as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+
+							/* mismatching key, no need to look further  */
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..a260074c91 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -251,6 +253,10 @@ brin_inclusion_add_value(PG_FUNCTION_ARGS)
 /*
  * BRIN inclusion consistent function
  *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
+ *
  * All of the strategies are optional.
  */
 Datum
@@ -258,24 +264,31 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/* Handle IS NULL/IS NOT NULL tests */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -284,7 +297,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -293,7 +311,14 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
@@ -301,10 +326,45 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all regular scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* Skip IS NULL/IS NOT NULL keys (already handled above). */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
+	/* This should be called only for regular keys, not for IS [NOT] NULL. */
+	Assert(!(key->sk_flags & SK_ISNULL));
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +384,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +444,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +464,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +483,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +518,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +528,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..e116084a02 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -140,29 +142,41 @@ brin_minmax_add_value(PG_FUNCTION_ARGS)
  * Given an index tuple corresponding to a certain page range and a scan key,
  * return whether the scan key is consistent with the index tuple's min/max
  * values.  Return true if so, false otherwise.
+ *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
  */
 Datum
 brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
 	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -171,7 +185,12 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -180,13 +199,52 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
+	}
+
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
+
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +287,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 1487710d59..33841e14f2 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8191,7 +8191,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------6A37408A2C42B5B56C3B3D49
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210303.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210303.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c          | 158 +++++++++++++++++++-----
 src/backend/access/brin/brin_validate.c |   4 +-
 2 files changed, 126 insertions(+), 36 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..963b7079cf 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,78 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of
+					 * multiple scan keys. We can determine that based on the
+					 * number of arguments - functions with extra parameter
+					 * (number of scan keys) do support this, otherwise we
+					 * have to simply pass the scan keys one by one, as
+					 * before.
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same
+						 * for all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet
+						 * the criteria for a single one of them is enough to
+						 * discard the range as a whole, so break out of the
+						 * loop as soon as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+
+							/* mismatching key, no need to look further  */
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-- 
2.26.2


--------------AC3FFB734F56C5F52D422EFC
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Process-all-scan-keys-in-existing-BRIN-opcl-20210305.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Process-all-scan-keys-in-existing-BRIN-opcl-20210305.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c          | 158 +++++++++++++++++++-----
 src/backend/access/brin/brin_validate.c |   4 +-
 2 files changed, 126 insertions(+), 36 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..f9a0476024 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,78 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any scan keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of
+					 * multiple scan keys. We can determine that based on the
+					 * number of arguments - functions with extra parameter
+					 * (number of scan keys) do support this, otherwise we
+					 * have to simply pass the scan keys one by one, as
+					 * before.
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same
+						 * for all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet
+						 * the criteria for a single one of them is enough to
+						 * discard the range as a whole, so break out of the
+						 * loop as soon as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+
+							/* mismatching key, no need to look further  */
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-- 
2.26.2


--------------82D677E9F94AC7574E460205
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Process-all-scan-keys-in-existing-BRIN-opcl-20210308.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Process-all-scan-keys-in-existing-BRIN-opcl-20210308.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c          | 158 +++++++++++++++++++-----
 src/backend/access/brin/brin_validate.c |   4 +-
 2 files changed, 126 insertions(+), 36 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..f9a0476024 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,78 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any scan keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of
+					 * multiple scan keys. We can determine that based on the
+					 * number of arguments - functions with extra parameter
+					 * (number of scan keys) do support this, otherwise we
+					 * have to simply pass the scan keys one by one, as
+					 * before.
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same
+						 * for all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet
+						 * the criteria for a single one of them is enough to
+						 * discard the range as a whole, so break out of the
+						 * loop as soon as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+
+							/* mismatching key, no need to look further  */
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-- 
2.26.2


--------------556A1DC61262AF15641DB204
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Process-all-scan-keys-in-existing-BRIN-opc-20210308b.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Process-all-scan-keys-in-existing-BRIN-opc-20210308b.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow future opclases to benefit from seeing all keys at once.

This does break existing BRIN opclasses, because the signature of the
consistent function changed. We might support both variants (with 3 and
4 parameters), but that seems pointless - the changes to NULL handling
likely require updates too. So better to make the failure clear. Also,
we're not aware of any out-of-core opclasses - there may be some, but
probably not many.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 doc/src/sgml/brin.sgml                   |   8 +-
 src/backend/access/brin/brin.c           | 118 +++++++++++++------
 src/backend/access/brin/brin_inclusion.c | 140 ++++++++++++++++-------
 src/backend/access/brin/brin_minmax.c    |  92 ++++++++++++---
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 6 files changed, 269 insertions(+), 97 deletions(-)

diff --git a/doc/src/sgml/brin.sgml b/doc/src/sgml/brin.sgml
index 06880c0f7b..078f51bb55 100644
--- a/doc/src/sgml/brin.sgml
+++ b/doc/src/sgml/brin.sgml
@@ -464,12 +464,14 @@ typedef struct BrinOpcInfo
 
    <varlistentry>
     <term><function>bool consistent(BrinDesc *bdesc, BrinValues *column,
-       ScanKey key)</function></term>
+       ScanKey *keys, int nkeys)</function></term>
     <listitem>
      <para>
-      Returns whether the ScanKey is consistent with the given indexed
-      values for a range.
+      Returns whether all the ScanKey entries are consistent with the given
+      indexed values for a range.
       The attribute number to use is passed as part of the scan key.
+      Multiple scan keys for the same attribute may be passed at once, the
+      number of entries is determined by the <literal>nkeys</literal> parameter.
      </para>
     </listitem>
    </varlistentry>
diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..743f2a925a 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,40 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
+					Oid			collation;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
-
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
-
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					/* skip attributes without any scan keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
+
+					bval = &dtup->bt_columns[attno - 1];
+
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * XXX We simply use the collation from the first key (it
+					 * has to be the same for all keys for the same attribue).
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
+					collation = keys[attno - 1][0]->sk_collation;
+
+					/* Check all keys at once */
+					add = FunctionCall4Coll(&consistentFn[attno - 1],
+											collation,
 											PointerGetDatum(bdesc),
 											PointerGetDatum(bval),
-											PointerGetDatum(key));
+											PointerGetDatum(keys[attno - 1]),
+											Int32GetDatum(nkeys[attno - 1]));
 					addrange = DatumGetBool(add);
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..a260074c91 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -251,6 +253,10 @@ brin_inclusion_add_value(PG_FUNCTION_ARGS)
 /*
  * BRIN inclusion consistent function
  *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
+ *
  * All of the strategies are optional.
  */
 Datum
@@ -258,24 +264,31 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/* Handle IS NULL/IS NOT NULL tests */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -284,7 +297,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -293,7 +311,14 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
@@ -301,10 +326,45 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all regular scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* Skip IS NULL/IS NOT NULL keys (already handled above). */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
+	/* This should be called only for regular keys, not for IS [NOT] NULL. */
+	Assert(!(key->sk_flags & SK_ISNULL));
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +384,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +444,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +464,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +483,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +518,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +528,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..e116084a02 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -140,29 +142,41 @@ brin_minmax_add_value(PG_FUNCTION_ARGS)
  * Given an index tuple corresponding to a certain page range and a scan key,
  * return whether the scan key is consistent with the index tuple's min/max
  * values.  Return true if so, false otherwise.
+ *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
  */
 Datum
 brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
 	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -171,7 +185,12 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -180,13 +199,52 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
+	}
+
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
+
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +287,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..2c4f9a3eff 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											4, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index c7619f8cd3..cd1eda38ab 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8223,7 +8223,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------D524CD37E77B36A2883A7617
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Move-IS-NOT-NULL-handling-from-BRIN-support-20210311.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Move-IS-NOT-NULL-handling-from-BRIN-support-20210311.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/9] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 4e0c9be58c..4099e72001 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8191,7 +8191,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------4B194FF8F3EA3786FF9EAE1F
Content-Type: application/vnd.oasis.opendocument.spreadsheet;
 name="brin-bench.ods"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
 filename="brin-bench.ods"

UEsDBBQAAAgAAOO7Q1KFbDmKLgAAAC4AAAAIAAAAbWltZXR5cGVhcHBsaWNhdGlvbi92bmQu
b2FzaXMub3BlbmRvY3VtZW50LnNwcmVhZHNoZWV0UEsDBBQAAAgAAOO7Q1IAAAAAAAAAAAAA
AAAcAAAAQ29uZmlndXJhdGlvbnMyL2FjY2VsZXJhdG9yL1BLAwQUAAAIAADju0NSAAAAAAAA
AAAAAAAAHwAAAENvbmZpZ3VyYXRpb25zMi9pbWFnZXMvQml0bWFwcy9QSwMEFAAACAAA47tD
UgAAAAAAAAAAAAAAABgAAABDb25maWd1cmF0aW9uczIvdG9vbGJhci9QSwMEFAAACAAA47tD
UgAAAAAAAAAAAAAAABgAAABDb25maWd1cmF0aW9uczIvZmxvYXRlci9QSwMEFAAACAAA47tD
UgAAAAAAAAAAAAAAABoAAABDb25maWd1cmF0aW9uczIvcG9wdXBtZW51L1BLAwQUAAAIAADj
u0NSAAAAAAAAAAAAAAAAGAAAAENvbmZpZ3VyYXRpb25zMi9tZW51YmFyL1BLAwQUAAAIAADj
u0NSAAAAAAAAAAAAAAAAGgAAAENvbmZpZ3VyYXRpb25zMi90b29scGFuZWwvUEsDBBQAAAgA
AOO7Q1IAAAAAAAAAAAAAAAAaAAAAQ29uZmlndXJhdGlvbnMyL3N0YXR1c2Jhci9QSwMEFAAA
CAAA47tDUgAAAAAAAAAAAAAAABwAAABDb25maWd1cmF0aW9uczIvcHJvZ3Jlc3NiYXIvUEsD
BBQACAgIAOO7Q1IAAAAAAAAAAAAAAAAMAAAAbWFuaWZlc3QucmRmzZPNboMwEITvPIVlzthA
LwUFcijKuWqfwDWGWAUv8poS3r6Ok1ZRpKrqn9TjrkYz3460m+1hHMiLsqjBVDRjKSXKSGi1
6Ss6uy65pds62ti2Kx+aHfFqg6WfKrp3bio5X5aFLTcMbM+zoih4mvM8T7wiwdU4cUgMxrSO
CAkejUJp9eR8GjnO4glmV1F066CQefcgPYvdOqmgsgphtlK9h7YgkYFAjQlMyoR0gxy6TkvF
M5bzUTnBoe3ix2C904OiPGDwK47P2N6IDKblXuC9sO5cg998lWh67mN6ddPF8d8jlGCcMu5P
6rs7ef/n/i7P/xnir7R2RGxAzqNn+pDntPIfVUevUEsHCLT3aNIFAQAAgwMAAFBLAwQUAAgI
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
qj3ilyQOPhr0ABLtL3rhZyov0EILLbTQQgsttND+W1rqv9n/cfyPtLu9/1v//Op6vYEY/1mt
W6p3rm9s+rFGaz8x2MF6O6wN/SU0Y2o3tvDifH1Jv4qU7vqardljWAZb3pyj1Tq6spysn/fd
2kTWub1a2+VJvKrVtXjeoiYdYprGsV9fxoqz3RtNUinHrl0haYvWpK6ELiWP4mOcD1bNUlgn
6uNKr69UXetjCoGnpsaut8D1spZC5LSaHJ0d1czXz8RDc7d5Xl9JkXeLGk6noLyv069jXdNk
vHUxiHZKk/clm/mSVvMxB7N+Wwrb+ur8Rl5vV7WKquUlh2kYw5Hzcn1uJ5KV344XmvjGZUpE
Stoq+wVtm/1QsoBjNO341mdqLcsKuza3xemjv4aNbm0aIxcZr6vahaTTlXfDKXC0/hPnbbIh
dLuFtK3JJRedK9LWwkv4dazpvPpsU+lmWzg6OQPk79IYL24UG9bslrl36/rubP6q+62s5Pf9
wHc1PnlNpg9l0CfL+PFzjx2XGxkfGnh7uNz5iO/djLTU957HpfBBL+pD0eqTRd9D7o/6e7y+
FvihAf0zWF0OlqCfvepL4Vohc/xLuiQb8JEHU5ZKK8zje+XvT6sPycePmnz4Ht4L/c7BjvxQ
okqyG1PpV7RJyfVaJ3XoNLfogiEllSAVaYLorhsnctwrZOQlenur3985r7+vxDrOVa7h5t79
g2aV7QOJ5jA3Zp3MfkE78spr5nXxXL0erGVDloocPvFtUd4Zmr3e9SJbgfZzf8nBurVNy3Qo
ye30uaENTd1KTi2JhPxyNutjV2NFaXsgTNKB5lK9tJLLyr5x1OeWrIjnTVJcK7mhyCW72Fil
RVKxeefJNrbtTDT4diYsRe0z70dtfGYwi2RAEm5b7UfOj82tm6eHlvLEeapzuaI957ZIJuBl
gM4pTefcynGfv+dXGCXispx2WSvuXdu8BEn6K6f8lk5tdzJYkhnObZP1/Nj3xHPwzGNa+Sog
s/Zr7b7Z3nVVh6qmhiXLeVvlkNdkzlZiYLWrbqpApuj7RLfd5Dy/acdUJWViard6qGJL9HmW
JnV9bG7H1LflgTDpfshB1wvavEn22sPOR5AlmSP9rHDmvp8P8kI+nxX5WC2UIh2V25Hlo+fZ
MrZt2+/VEs/L1vHg3PIeHhmmXbofb0eC/RZaaKGFFlpooYUWWmihhRZaaKGFFlpooYUWWmih
hRZaaKGFFlpooYUWWmihhRZaaKGFFlpooYUWWmihhRZaaKGFFlpooYUWWmihhRZaaKGFFlpo
oYUWWmih/bLlfnc6eg4tzW5mTt+eQxvjcfBx3sruGbR+XhTZ41m0hZ33fTqeQls86bhtr+U5
rsmbPe/DvmK/hRZaaKGFFlpooYUWWmihhRZaaKGFFlpooYUWWmihhRZaaKGFFlpooYUWWmih
hRZaaKGFFlpooYUWWmihhRZaaKGFFlpooYUWWmihhRZaaKGFFlpooYUWWmi/aDnvfXe/C954
Am29Re7KzkMv+uvfO6yGyG1nXRyv+euvZNEyt5mVmegJtIk5WzrnNn55LYXAzQzKnrbw5bWL
MWs01u6bXwn7LbTQQgsttNBCCy200EILLbTQQgsttNBCCy200EILLbTQQgsttNBCCy200EIL
LbTQQgsttNBCCy200EILLbTQQvtfLX8AMeK8L/Il6gcAAAAASUVORK5CYIJQSwMEFAAICAgA
47tDUgAAAAAAAAAAAAAAABUAAABNRVRBLUlORi9tYW5pZmVzdC54bWytk01uwyAQRvc5hcW2
MrRZVShOFpF6gvQA1AwOEh4QDFFy+2IrTlxVkWIpO36G9z0Gsdmde1edICbrsWEf/J1VgK3X
FruGfR++6k+22642vUJrIJGcBlU5h+k2bViOKL1KNklUPSRJrfQBUPs294Ak/9bLMek2mwms
2RXtPJwnbuzkBDI+o1ZUqq9BcA4Q7bClnPTG2BbkjDAmbVfV/QrGOqhLebzcBUx2rg6Kjg0T
D73uTQBtVU2XAA1TITjbjkLihJqPPeDzq/MUIiidjgDExBKVvUdjuxxHelqLJxVSRl46wLPl
7ZywLHxa41GbJ4JL1VsJXZgBpAbVB3wq7ycWQxNdHKSXY0sraXjNl+sCUfltrxc+HHP/g8q6
JGga8oDdgxDbqw7EsF9SNuLfj9/+AlBLBwiY3t5QMQEAACwEAABQSwECFAAUAAAIAADju0NS
hWw5ii4AAAAuAAAACAAAAAAAAAAAAAAAAAAAAAAAbWltZXR5cGVQSwECFAAUAAAIAADju0NS
AAAAAAAAAAAAAAAAHAAAAAAAAAAAAAAAAABUAAAAQ29uZmlndXJhdGlvbnMyL2FjY2VsZXJh
dG9yL1BLAQIUABQAAAgAAOO7Q1IAAAAAAAAAAAAAAAAfAAAAAAAAAAAAAAAAAI4AAABDb25m
aWd1cmF0aW9uczIvaW1hZ2VzL0JpdG1hcHMvUEsBAhQAFAAACAAA47tDUgAAAAAAAAAAAAAA
ABgAAAAAAAAAAAAAAAAAywAAAENvbmZpZ3VyYXRpb25zMi90b29sYmFyL1BLAQIUABQAAAgA
AOO7Q1IAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAAEBAABDb25maWd1cmF0aW9uczIvZmxv
YXRlci9QSwECFAAUAAAIAADju0NSAAAAAAAAAAAAAAAAGgAAAAAAAAAAAAAAAAA3AQAAQ29u
ZmlndXJhdGlvbnMyL3BvcHVwbWVudS9QSwECFAAUAAAIAADju0NSAAAAAAAAAAAAAAAAGAAA
AAAAAAAAAAAAAABvAQAAQ29uZmlndXJhdGlvbnMyL21lbnViYXIvUEsBAhQAFAAACAAA47tD
UgAAAAAAAAAAAAAAABoAAAAAAAAAAAAAAAAApQEAAENvbmZpZ3VyYXRpb25zMi90b29scGFu
ZWwvUEsBAhQAFAAACAAA47tDUgAAAAAAAAAAAAAAABoAAAAAAAAAAAAAAAAA3QEAAENvbmZp
Z3VyYXRpb25zMi9zdGF0dXNiYXIvUEsBAhQAFAAACAAA47tDUgAAAAAAAAAAAAAAABwAAAAA
AAAAAAAAAAAAFQIAAENvbmZpZ3VyYXRpb25zMi9wcm9ncmVzc2Jhci9QSwECFAAUAAgICADj
u0NStPdo0gUBAACDAwAADAAAAAAAAAAAAAAAAABPAgAAbWFuaWZlc3QucmRmUEsBAhQAFAAI
CAgA47tDUkPmqgiEAQAABQMAAAgAAAAAAAAAAAAAAAAAjgMAAG1ldGEueG1sUEsBAhQAFAAI
CAgA47tDUiKRfp7VCgAAsV8AAAoAAAAAAAAAAAAAAAAASAUAAHN0eWxlcy54bWxQSwECFAAU
AAgICADju0NSYLGE3xSxAwCYmUQACwAAAAAAAAAAAAAAAABVEAAAY29udGVudC54bWxQSwEC
FAAUAAgICADju0NSryN3l3MFAADvIgAADAAAAAAAAAAAAAAAAACiwQMAc2V0dGluZ3MueG1s
UEsBAhQAFAAACAAA47tDUkFRsCC1BQAAtQUAABgAAAAAAAAAAAAAAAAAT8cDAFRodW1ibmFp
bHMvdGh1bWJuYWlsLnBuZ1BLAQIUABQACAgIAOO7Q1KY3t5QMQEAACwEAAAVAAAAAAAAAAAA
AAAAADrNAwBNRVRBLUlORi9tYW5pZmVzdC54bWxQSwUGAAAAABEAEQBlBAAArs4DAAAA
--------------4B194FF8F3EA3786FF9EAE1F
Content-Type: application/x-compressed-tar;
 name="brin-stress-test.tgz"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
 filename="brin-stress-test.tgz"

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
4sSJE/vk/y10LU4AkAEA
--------------4B194FF8F3EA3786FF9EAE1F
Content-Type: application/x-compressed-tar;
 name="brin-bench.tgz"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
 filename="brin-bench.tgz"

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
--------------4B194FF8F3EA3786FF9EAE1F--





^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/9] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 4e0c9be58c..4099e72001 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8191,7 +8191,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------0E72B707603BED22B4040825--





^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/9] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 1487710d59..33841e14f2 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8191,7 +8191,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------22A4B241170149838D4D1F8F
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210215.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210215.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 58fe109d2d..8a1a9da78f 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -389,6 +389,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -410,6 +413,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -470,7 +528,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -480,51 +538,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index d7b55f57ea..871e024e00 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8143,7 +8143,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8159,7 +8159,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------CF71AF65F7C337C37C24B045
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210112.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210112.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/6] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 58fe109d2d..8a1a9da78f 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -389,6 +389,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -410,6 +413,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -470,7 +528,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -480,51 +538,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index d7b55f57ea..871e024e00 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8143,7 +8143,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8159,7 +8159,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------D21F32E0F9E7408E9BE1AF2E
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210114.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210114.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/6] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index d27336adcd..f3ead7d53d 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8145,7 +8145,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8161,7 +8161,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------310A2AE1CC4C2E2E77559E3D
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-suppo-20210114-2.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-suppo-20210114-2.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index b5f52d4e4a..2ef11245a8 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8183,7 +8183,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8199,7 +8199,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------FA974B75A0C3E9CA18CE7207
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210122.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210122.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/6] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 158 ++++++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 140 ++++++++++++++------
 src/backend/access/brin/brin_minmax.c    |  92 ++++++++++---
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 303 insertions(+), 95 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..963b7079cf 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,78 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of
+					 * multiple scan keys. We can determine that based on the
+					 * number of arguments - functions with extra parameter
+					 * (number of scan keys) do support this, otherwise we
+					 * have to simply pass the scan keys one by one, as
+					 * before.
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same
+						 * for all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet
+						 * the criteria for a single one of them is enough to
+						 * discard the range as a whole, so break out of the
+						 * loop as soon as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+
+							/* mismatching key, no need to look further  */
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..a260074c91 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -251,6 +253,10 @@ brin_inclusion_add_value(PG_FUNCTION_ARGS)
 /*
  * BRIN inclusion consistent function
  *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
+ *
  * All of the strategies are optional.
  */
 Datum
@@ -258,24 +264,31 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/* Handle IS NULL/IS NOT NULL tests */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -284,7 +297,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -293,7 +311,14 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
@@ -301,10 +326,45 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all regular scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* Skip IS NULL/IS NOT NULL keys (already handled above). */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
+	/* This should be called only for regular keys, not for IS [NOT] NULL. */
+	Assert(!(key->sk_flags & SK_ISNULL));
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +384,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +444,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +464,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +483,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +518,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +528,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..e116084a02 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -140,29 +142,41 @@ brin_minmax_add_value(PG_FUNCTION_ARGS)
  * Given an index tuple corresponding to a certain page range and a scan key,
  * return whether the scan key is consistent with the index tuple's min/max
  * values.  Return true if so, false otherwise.
+ *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
  */
 Datum
 brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
 	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -171,7 +185,12 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -180,13 +199,52 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
+	}
+
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
+
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +287,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 1487710d59..33841e14f2 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8191,7 +8191,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------6A37408A2C42B5B56C3B3D49
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210303.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210303.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c          | 158 +++++++++++++++++++-----
 src/backend/access/brin/brin_validate.c |   4 +-
 2 files changed, 126 insertions(+), 36 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..f9a0476024 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,78 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any scan keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of
+					 * multiple scan keys. We can determine that based on the
+					 * number of arguments - functions with extra parameter
+					 * (number of scan keys) do support this, otherwise we
+					 * have to simply pass the scan keys one by one, as
+					 * before.
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same
+						 * for all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet
+						 * the criteria for a single one of them is enough to
+						 * discard the range as a whole, so break out of the
+						 * loop as soon as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+
+							/* mismatching key, no need to look further  */
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-- 
2.26.2


--------------82D677E9F94AC7574E460205
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Process-all-scan-keys-in-existing-BRIN-opcl-20210308.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Process-all-scan-keys-in-existing-BRIN-opcl-20210308.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c          | 158 +++++++++++++++++++-----
 src/backend/access/brin/brin_validate.c |   4 +-
 2 files changed, 126 insertions(+), 36 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..f9a0476024 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,78 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any scan keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of
+					 * multiple scan keys. We can determine that based on the
+					 * number of arguments - functions with extra parameter
+					 * (number of scan keys) do support this, otherwise we
+					 * have to simply pass the scan keys one by one, as
+					 * before.
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same
+						 * for all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet
+						 * the criteria for a single one of them is enough to
+						 * discard the range as a whole, so break out of the
+						 * loop as soon as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+
+							/* mismatching key, no need to look further  */
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-- 
2.26.2


--------------556A1DC61262AF15641DB204
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Process-all-scan-keys-in-existing-BRIN-opc-20210308b.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Process-all-scan-keys-in-existing-BRIN-opc-20210308b.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow future opclases to benefit from seeing all keys at once.

This does break existing BRIN opclasses, because the signature of the
consistent function changed. We might support both variants (with 3 and
4 parameters), but that seems pointless - the changes to NULL handling
likely require updates too. So better to make the failure clear. Also,
we're not aware of any out-of-core opclasses - there may be some, but
probably not many.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 doc/src/sgml/brin.sgml                   |   8 +-
 src/backend/access/brin/brin.c           | 118 +++++++++++++------
 src/backend/access/brin/brin_inclusion.c | 140 ++++++++++++++++-------
 src/backend/access/brin/brin_minmax.c    |  92 ++++++++++++---
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 6 files changed, 269 insertions(+), 97 deletions(-)

diff --git a/doc/src/sgml/brin.sgml b/doc/src/sgml/brin.sgml
index 06880c0f7b..078f51bb55 100644
--- a/doc/src/sgml/brin.sgml
+++ b/doc/src/sgml/brin.sgml
@@ -464,12 +464,14 @@ typedef struct BrinOpcInfo
 
    <varlistentry>
     <term><function>bool consistent(BrinDesc *bdesc, BrinValues *column,
-       ScanKey key)</function></term>
+       ScanKey *keys, int nkeys)</function></term>
     <listitem>
      <para>
-      Returns whether the ScanKey is consistent with the given indexed
-      values for a range.
+      Returns whether all the ScanKey entries are consistent with the given
+      indexed values for a range.
       The attribute number to use is passed as part of the scan key.
+      Multiple scan keys for the same attribute may be passed at once, the
+      number of entries is determined by the <literal>nkeys</literal> parameter.
      </para>
     </listitem>
    </varlistentry>
diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..743f2a925a 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,40 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
+					Oid			collation;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
-
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
-
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					/* skip attributes without any scan keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
+
+					bval = &dtup->bt_columns[attno - 1];
+
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * XXX We simply use the collation from the first key (it
+					 * has to be the same for all keys for the same attribue).
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
+					collation = keys[attno - 1][0]->sk_collation;
+
+					/* Check all keys at once */
+					add = FunctionCall4Coll(&consistentFn[attno - 1],
+											collation,
 											PointerGetDatum(bdesc),
 											PointerGetDatum(bval),
-											PointerGetDatum(key));
+											PointerGetDatum(keys[attno - 1]),
+											Int32GetDatum(nkeys[attno - 1]));
 					addrange = DatumGetBool(add);
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..a260074c91 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -251,6 +253,10 @@ brin_inclusion_add_value(PG_FUNCTION_ARGS)
 /*
  * BRIN inclusion consistent function
  *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
+ *
  * All of the strategies are optional.
  */
 Datum
@@ -258,24 +264,31 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/* Handle IS NULL/IS NOT NULL tests */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -284,7 +297,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -293,7 +311,14 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
@@ -301,10 +326,45 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all regular scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* Skip IS NULL/IS NOT NULL keys (already handled above). */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
+	/* This should be called only for regular keys, not for IS [NOT] NULL. */
+	Assert(!(key->sk_flags & SK_ISNULL));
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +384,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +444,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +464,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +483,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +518,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +528,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..e116084a02 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -140,29 +142,41 @@ brin_minmax_add_value(PG_FUNCTION_ARGS)
  * Given an index tuple corresponding to a certain page range and a scan key,
  * return whether the scan key is consistent with the index tuple's min/max
  * values.  Return true if so, false otherwise.
+ *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
  */
 Datum
 brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
 	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -171,7 +185,12 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -180,13 +199,52 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
+	}
+
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
+
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +287,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..2c4f9a3eff 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											4, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index c7619f8cd3..cd1eda38ab 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8223,7 +8223,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------D524CD37E77B36A2883A7617
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Move-IS-NOT-NULL-handling-from-BRIN-support-20210311.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Move-IS-NOT-NULL-handling-from-BRIN-support-20210311.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c          | 158 +++++++++++++++++++-----
 src/backend/access/brin/brin_validate.c |   4 +-
 2 files changed, 126 insertions(+), 36 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..f9a0476024 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,78 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any scan keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of
+					 * multiple scan keys. We can determine that based on the
+					 * number of arguments - functions with extra parameter
+					 * (number of scan keys) do support this, otherwise we
+					 * have to simply pass the scan keys one by one, as
+					 * before.
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same
+						 * for all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet
+						 * the criteria for a single one of them is enough to
+						 * discard the range as a whole, so break out of the
+						 * loop as soon as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+
+							/* mismatching key, no need to look further  */
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-- 
2.26.2


--------------82D677E9F94AC7574E460205
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Process-all-scan-keys-in-existing-BRIN-opcl-20210308.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Process-all-scan-keys-in-existing-BRIN-opcl-20210308.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c          | 158 +++++++++++++++++++-----
 src/backend/access/brin/brin_validate.c |   4 +-
 2 files changed, 126 insertions(+), 36 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..f9a0476024 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,78 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any scan keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of
+					 * multiple scan keys. We can determine that based on the
+					 * number of arguments - functions with extra parameter
+					 * (number of scan keys) do support this, otherwise we
+					 * have to simply pass the scan keys one by one, as
+					 * before.
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same
+						 * for all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet
+						 * the criteria for a single one of them is enough to
+						 * discard the range as a whole, so break out of the
+						 * loop as soon as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+
+							/* mismatching key, no need to look further  */
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-- 
2.26.2


--------------556A1DC61262AF15641DB204
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Process-all-scan-keys-in-existing-BRIN-opc-20210308b.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Process-all-scan-keys-in-existing-BRIN-opc-20210308b.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow future opclases to benefit from seeing all keys at once.

This does break existing BRIN opclasses, because the signature of the
consistent function changed. We might support both variants (with 3 and
4 parameters), but that seems pointless - the changes to NULL handling
likely require updates too. So better to make the failure clear. Also,
we're not aware of any out-of-core opclasses - there may be some, but
probably not many.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 doc/src/sgml/brin.sgml                   |   8 +-
 src/backend/access/brin/brin.c           | 118 +++++++++++++------
 src/backend/access/brin/brin_inclusion.c | 140 ++++++++++++++++-------
 src/backend/access/brin/brin_minmax.c    |  92 ++++++++++++---
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 6 files changed, 269 insertions(+), 97 deletions(-)

diff --git a/doc/src/sgml/brin.sgml b/doc/src/sgml/brin.sgml
index 06880c0f7b..078f51bb55 100644
--- a/doc/src/sgml/brin.sgml
+++ b/doc/src/sgml/brin.sgml
@@ -464,12 +464,14 @@ typedef struct BrinOpcInfo
 
    <varlistentry>
     <term><function>bool consistent(BrinDesc *bdesc, BrinValues *column,
-       ScanKey key)</function></term>
+       ScanKey *keys, int nkeys)</function></term>
     <listitem>
      <para>
-      Returns whether the ScanKey is consistent with the given indexed
-      values for a range.
+      Returns whether all the ScanKey entries are consistent with the given
+      indexed values for a range.
       The attribute number to use is passed as part of the scan key.
+      Multiple scan keys for the same attribute may be passed at once, the
+      number of entries is determined by the <literal>nkeys</literal> parameter.
      </para>
     </listitem>
    </varlistentry>
diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..743f2a925a 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,40 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
+					Oid			collation;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
-
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
-
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					/* skip attributes without any scan keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
+
+					bval = &dtup->bt_columns[attno - 1];
+
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * XXX We simply use the collation from the first key (it
+					 * has to be the same for all keys for the same attribue).
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
+					collation = keys[attno - 1][0]->sk_collation;
+
+					/* Check all keys at once */
+					add = FunctionCall4Coll(&consistentFn[attno - 1],
+											collation,
 											PointerGetDatum(bdesc),
 											PointerGetDatum(bval),
-											PointerGetDatum(key));
+											PointerGetDatum(keys[attno - 1]),
+											Int32GetDatum(nkeys[attno - 1]));
 					addrange = DatumGetBool(add);
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..a260074c91 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -251,6 +253,10 @@ brin_inclusion_add_value(PG_FUNCTION_ARGS)
 /*
  * BRIN inclusion consistent function
  *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
+ *
  * All of the strategies are optional.
  */
 Datum
@@ -258,24 +264,31 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/* Handle IS NULL/IS NOT NULL tests */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -284,7 +297,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -293,7 +311,14 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
@@ -301,10 +326,45 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all regular scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* Skip IS NULL/IS NOT NULL keys (already handled above). */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
+	/* This should be called only for regular keys, not for IS [NOT] NULL. */
+	Assert(!(key->sk_flags & SK_ISNULL));
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +384,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +444,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +464,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +483,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +518,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +528,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..e116084a02 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -140,29 +142,41 @@ brin_minmax_add_value(PG_FUNCTION_ARGS)
  * Given an index tuple corresponding to a certain page range and a scan key,
  * return whether the scan key is consistent with the index tuple's min/max
  * values.  Return true if so, false otherwise.
+ *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
  */
 Datum
 brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
 	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -171,7 +185,12 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -180,13 +199,52 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
+	}
+
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
+
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +287,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..2c4f9a3eff 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											4, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index c7619f8cd3..cd1eda38ab 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8223,7 +8223,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------D524CD37E77B36A2883A7617
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Move-IS-NOT-NULL-handling-from-BRIN-support-20210311.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Move-IS-NOT-NULL-handling-from-BRIN-support-20210311.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/9] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 4e0c9be58c..4099e72001 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8191,7 +8191,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------4B194FF8F3EA3786FF9EAE1F
Content-Type: application/vnd.oasis.opendocument.spreadsheet;
 name="brin-bench.ods"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
 filename="brin-bench.ods"

UEsDBBQAAAgAAOO7Q1KFbDmKLgAAAC4AAAAIAAAAbWltZXR5cGVhcHBsaWNhdGlvbi92bmQu
b2FzaXMub3BlbmRvY3VtZW50LnNwcmVhZHNoZWV0UEsDBBQAAAgAAOO7Q1IAAAAAAAAAAAAA
AAAcAAAAQ29uZmlndXJhdGlvbnMyL2FjY2VsZXJhdG9yL1BLAwQUAAAIAADju0NSAAAAAAAA
AAAAAAAAHwAAAENvbmZpZ3VyYXRpb25zMi9pbWFnZXMvQml0bWFwcy9QSwMEFAAACAAA47tD
UgAAAAAAAAAAAAAAABgAAABDb25maWd1cmF0aW9uczIvdG9vbGJhci9QSwMEFAAACAAA47tD
UgAAAAAAAAAAAAAAABgAAABDb25maWd1cmF0aW9uczIvZmxvYXRlci9QSwMEFAAACAAA47tD
UgAAAAAAAAAAAAAAABoAAABDb25maWd1cmF0aW9uczIvcG9wdXBtZW51L1BLAwQUAAAIAADj
u0NSAAAAAAAAAAAAAAAAGAAAAENvbmZpZ3VyYXRpb25zMi9tZW51YmFyL1BLAwQUAAAIAADj
u0NSAAAAAAAAAAAAAAAAGgAAAENvbmZpZ3VyYXRpb25zMi90b29scGFuZWwvUEsDBBQAAAgA
AOO7Q1IAAAAAAAAAAAAAAAAaAAAAQ29uZmlndXJhdGlvbnMyL3N0YXR1c2Jhci9QSwMEFAAA
CAAA47tDUgAAAAAAAAAAAAAAABwAAABDb25maWd1cmF0aW9uczIvcHJvZ3Jlc3NiYXIvUEsD
BBQACAgIAOO7Q1IAAAAAAAAAAAAAAAAMAAAAbWFuaWZlc3QucmRmzZPNboMwEITvPIVlzthA
LwUFcijKuWqfwDWGWAUv8poS3r6Ok1ZRpKrqn9TjrkYz3460m+1hHMiLsqjBVDRjKSXKSGi1
6Ss6uy65pds62ti2Kx+aHfFqg6WfKrp3bio5X5aFLTcMbM+zoih4mvM8T7wiwdU4cUgMxrSO
CAkejUJp9eR8GjnO4glmV1F066CQefcgPYvdOqmgsgphtlK9h7YgkYFAjQlMyoR0gxy6TkvF
M5bzUTnBoe3ix2C904OiPGDwK47P2N6IDKblXuC9sO5cg998lWh67mN6ddPF8d8jlGCcMu5P
6rs7ef/n/i7P/xnir7R2RGxAzqNn+pDntPIfVUevUEsHCLT3aNIFAQAAgwMAAFBLAwQUAAgI
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
qj3ilyQOPhr0ABLtL3rhZyov0EILLbTQQgsttND+W1rqv9n/cfyPtLu9/1v//Op6vYEY/1mt
W6p3rm9s+rFGaz8x2MF6O6wN/SU0Y2o3tvDifH1Jv4qU7vqardljWAZb3pyj1Tq6spysn/fd
2kTWub1a2+VJvKrVtXjeoiYdYprGsV9fxoqz3RtNUinHrl0haYvWpK6ELiWP4mOcD1bNUlgn
6uNKr69UXetjCoGnpsaut8D1spZC5LSaHJ0d1czXz8RDc7d5Xl9JkXeLGk6noLyv069jXdNk
vHUxiHZKk/clm/mSVvMxB7N+Wwrb+ur8Rl5vV7WKquUlh2kYw5Hzcn1uJ5KV344XmvjGZUpE
Stoq+wVtm/1QsoBjNO341mdqLcsKuza3xemjv4aNbm0aIxcZr6vahaTTlXfDKXC0/hPnbbIh
dLuFtK3JJRedK9LWwkv4dazpvPpsU+lmWzg6OQPk79IYL24UG9bslrl36/rubP6q+62s5Pf9
wHc1PnlNpg9l0CfL+PFzjx2XGxkfGnh7uNz5iO/djLTU957HpfBBL+pD0eqTRd9D7o/6e7y+
FvihAf0zWF0OlqCfvepL4Vohc/xLuiQb8JEHU5ZKK8zje+XvT6sPycePmnz4Ht4L/c7BjvxQ
okqyG1PpV7RJyfVaJ3XoNLfogiEllSAVaYLorhsnctwrZOQlenur3985r7+vxDrOVa7h5t79
g2aV7QOJ5jA3Zp3MfkE78spr5nXxXL0erGVDloocPvFtUd4Zmr3e9SJbgfZzf8nBurVNy3Qo
ye30uaENTd1KTi2JhPxyNutjV2NFaXsgTNKB5lK9tJLLyr5x1OeWrIjnTVJcK7mhyCW72Fil
RVKxeefJNrbtTDT4diYsRe0z70dtfGYwi2RAEm5b7UfOj82tm6eHlvLEeapzuaI957ZIJuBl
gM4pTefcynGfv+dXGCXispx2WSvuXdu8BEn6K6f8lk5tdzJYkhnObZP1/Nj3xHPwzGNa+Sog
s/Zr7b7Z3nVVh6qmhiXLeVvlkNdkzlZiYLWrbqpApuj7RLfd5Dy/acdUJWViard6qGJL9HmW
JnV9bG7H1LflgTDpfshB1wvavEn22sPOR5AlmSP9rHDmvp8P8kI+nxX5WC2UIh2V25Hlo+fZ
MrZt2+/VEs/L1vHg3PIeHhmmXbofb0eC/RZaaKGFFlpooYUWWmihhRZaaKGFFlpooYUWWmih
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
--------------4B194FF8F3EA3786FF9EAE1F
Content-Type: application/x-compressed-tar;
 name="brin-stress-test.tgz"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
 filename="brin-stress-test.tgz"

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
4sSJE/vk/y10LU4AkAEA
--------------4B194FF8F3EA3786FF9EAE1F
Content-Type: application/x-compressed-tar;
 name="brin-bench.tgz"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
 filename="brin-bench.tgz"

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
--------------4B194FF8F3EA3786FF9EAE1F--





^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/9] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 4e0c9be58c..4099e72001 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8191,7 +8191,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------0E72B707603BED22B4040825--





^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/9] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 1487710d59..33841e14f2 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8191,7 +8191,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------22A4B241170149838D4D1F8F
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210215.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210215.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 58fe109d2d..8a1a9da78f 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -389,6 +389,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -410,6 +413,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -470,7 +528,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -480,51 +538,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index d7b55f57ea..871e024e00 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8143,7 +8143,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8159,7 +8159,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------CF71AF65F7C337C37C24B045
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210112.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210112.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/6] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 58fe109d2d..8a1a9da78f 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -389,6 +389,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -410,6 +413,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -470,7 +528,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -480,51 +538,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index d7b55f57ea..871e024e00 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8143,7 +8143,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8159,7 +8159,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------D21F32E0F9E7408E9BE1AF2E
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210114.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210114.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/6] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index d27336adcd..f3ead7d53d 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8145,7 +8145,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8161,7 +8161,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------310A2AE1CC4C2E2E77559E3D
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-suppo-20210114-2.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-suppo-20210114-2.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index b5f52d4e4a..2ef11245a8 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8183,7 +8183,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8199,7 +8199,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------FA974B75A0C3E9CA18CE7207
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210122.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210122.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/6] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 158 ++++++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 140 ++++++++++++++------
 src/backend/access/brin/brin_minmax.c    |  92 ++++++++++---
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 303 insertions(+), 95 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..963b7079cf 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,78 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of
+					 * multiple scan keys. We can determine that based on the
+					 * number of arguments - functions with extra parameter
+					 * (number of scan keys) do support this, otherwise we
+					 * have to simply pass the scan keys one by one, as
+					 * before.
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same
+						 * for all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet
+						 * the criteria for a single one of them is enough to
+						 * discard the range as a whole, so break out of the
+						 * loop as soon as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+
+							/* mismatching key, no need to look further  */
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..a260074c91 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -251,6 +253,10 @@ brin_inclusion_add_value(PG_FUNCTION_ARGS)
 /*
  * BRIN inclusion consistent function
  *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
+ *
  * All of the strategies are optional.
  */
 Datum
@@ -258,24 +264,31 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/* Handle IS NULL/IS NOT NULL tests */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -284,7 +297,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -293,7 +311,14 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
@@ -301,10 +326,45 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all regular scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* Skip IS NULL/IS NOT NULL keys (already handled above). */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
+	/* This should be called only for regular keys, not for IS [NOT] NULL. */
+	Assert(!(key->sk_flags & SK_ISNULL));
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +384,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +444,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +464,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +483,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +518,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +528,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..e116084a02 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -140,29 +142,41 @@ brin_minmax_add_value(PG_FUNCTION_ARGS)
  * Given an index tuple corresponding to a certain page range and a scan key,
  * return whether the scan key is consistent with the index tuple's min/max
  * values.  Return true if so, false otherwise.
+ *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
  */
 Datum
 brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
 	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -171,7 +185,12 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -180,13 +199,52 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
+	}
+
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
+
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +287,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 1487710d59..33841e14f2 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8191,7 +8191,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------6A37408A2C42B5B56C3B3D49
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210303.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210303.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c          | 158 +++++++++++++++++++-----
 src/backend/access/brin/brin_validate.c |   4 +-
 2 files changed, 126 insertions(+), 36 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..963b7079cf 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,78 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of
+					 * multiple scan keys. We can determine that based on the
+					 * number of arguments - functions with extra parameter
+					 * (number of scan keys) do support this, otherwise we
+					 * have to simply pass the scan keys one by one, as
+					 * before.
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same
+						 * for all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet
+						 * the criteria for a single one of them is enough to
+						 * discard the range as a whole, so break out of the
+						 * loop as soon as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+
+							/* mismatching key, no need to look further  */
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-- 
2.26.2


--------------AC3FFB734F56C5F52D422EFC
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Process-all-scan-keys-in-existing-BRIN-opcl-20210305.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Process-all-scan-keys-in-existing-BRIN-opcl-20210305.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c          | 158 +++++++++++++++++++-----
 src/backend/access/brin/brin_validate.c |   4 +-
 2 files changed, 126 insertions(+), 36 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..f9a0476024 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,78 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any scan keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of
+					 * multiple scan keys. We can determine that based on the
+					 * number of arguments - functions with extra parameter
+					 * (number of scan keys) do support this, otherwise we
+					 * have to simply pass the scan keys one by one, as
+					 * before.
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same
+						 * for all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet
+						 * the criteria for a single one of them is enough to
+						 * discard the range as a whole, so break out of the
+						 * loop as soon as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+
+							/* mismatching key, no need to look further  */
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-- 
2.26.2


--------------82D677E9F94AC7574E460205
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Process-all-scan-keys-in-existing-BRIN-opcl-20210308.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Process-all-scan-keys-in-existing-BRIN-opcl-20210308.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c          | 158 +++++++++++++++++++-----
 src/backend/access/brin/brin_validate.c |   4 +-
 2 files changed, 126 insertions(+), 36 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..f9a0476024 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,78 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any scan keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of
+					 * multiple scan keys. We can determine that based on the
+					 * number of arguments - functions with extra parameter
+					 * (number of scan keys) do support this, otherwise we
+					 * have to simply pass the scan keys one by one, as
+					 * before.
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same
+						 * for all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet
+						 * the criteria for a single one of them is enough to
+						 * discard the range as a whole, so break out of the
+						 * loop as soon as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+
+							/* mismatching key, no need to look further  */
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-- 
2.26.2


--------------556A1DC61262AF15641DB204
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Process-all-scan-keys-in-existing-BRIN-opc-20210308b.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Process-all-scan-keys-in-existing-BRIN-opc-20210308b.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow future opclases to benefit from seeing all keys at once.

This does break existing BRIN opclasses, because the signature of the
consistent function changed. We might support both variants (with 3 and
4 parameters), but that seems pointless - the changes to NULL handling
likely require updates too. So better to make the failure clear. Also,
we're not aware of any out-of-core opclasses - there may be some, but
probably not many.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 doc/src/sgml/brin.sgml                   |   8 +-
 src/backend/access/brin/brin.c           | 118 +++++++++++++------
 src/backend/access/brin/brin_inclusion.c | 140 ++++++++++++++++-------
 src/backend/access/brin/brin_minmax.c    |  92 ++++++++++++---
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 6 files changed, 269 insertions(+), 97 deletions(-)

diff --git a/doc/src/sgml/brin.sgml b/doc/src/sgml/brin.sgml
index 06880c0f7b..078f51bb55 100644
--- a/doc/src/sgml/brin.sgml
+++ b/doc/src/sgml/brin.sgml
@@ -464,12 +464,14 @@ typedef struct BrinOpcInfo
 
    <varlistentry>
     <term><function>bool consistent(BrinDesc *bdesc, BrinValues *column,
-       ScanKey key)</function></term>
+       ScanKey *keys, int nkeys)</function></term>
     <listitem>
      <para>
-      Returns whether the ScanKey is consistent with the given indexed
-      values for a range.
+      Returns whether all the ScanKey entries are consistent with the given
+      indexed values for a range.
       The attribute number to use is passed as part of the scan key.
+      Multiple scan keys for the same attribute may be passed at once, the
+      number of entries is determined by the <literal>nkeys</literal> parameter.
      </para>
     </listitem>
    </varlistentry>
diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..743f2a925a 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,40 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
+					Oid			collation;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
-
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
-
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					/* skip attributes without any scan keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
+
+					bval = &dtup->bt_columns[attno - 1];
+
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * XXX We simply use the collation from the first key (it
+					 * has to be the same for all keys for the same attribue).
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
+					collation = keys[attno - 1][0]->sk_collation;
+
+					/* Check all keys at once */
+					add = FunctionCall4Coll(&consistentFn[attno - 1],
+											collation,
 											PointerGetDatum(bdesc),
 											PointerGetDatum(bval),
-											PointerGetDatum(key));
+											PointerGetDatum(keys[attno - 1]),
+											Int32GetDatum(nkeys[attno - 1]));
 					addrange = DatumGetBool(add);
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..a260074c91 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -251,6 +253,10 @@ brin_inclusion_add_value(PG_FUNCTION_ARGS)
 /*
  * BRIN inclusion consistent function
  *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
+ *
  * All of the strategies are optional.
  */
 Datum
@@ -258,24 +264,31 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/* Handle IS NULL/IS NOT NULL tests */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -284,7 +297,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -293,7 +311,14 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
@@ -301,10 +326,45 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all regular scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* Skip IS NULL/IS NOT NULL keys (already handled above). */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
+	/* This should be called only for regular keys, not for IS [NOT] NULL. */
+	Assert(!(key->sk_flags & SK_ISNULL));
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +384,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +444,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +464,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +483,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +518,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +528,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..e116084a02 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -140,29 +142,41 @@ brin_minmax_add_value(PG_FUNCTION_ARGS)
  * Given an index tuple corresponding to a certain page range and a scan key,
  * return whether the scan key is consistent with the index tuple's min/max
  * values.  Return true if so, false otherwise.
+ *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
  */
 Datum
 brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
 	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -171,7 +185,12 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -180,13 +199,52 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
+	}
+
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
+
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +287,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..2c4f9a3eff 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											4, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index c7619f8cd3..cd1eda38ab 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8223,7 +8223,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------D524CD37E77B36A2883A7617
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Move-IS-NOT-NULL-handling-from-BRIN-support-20210311.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Move-IS-NOT-NULL-handling-from-BRIN-support-20210311.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/9] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 4e0c9be58c..4099e72001 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8191,7 +8191,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------4B194FF8F3EA3786FF9EAE1F
Content-Type: application/vnd.oasis.opendocument.spreadsheet;
 name="brin-bench.ods"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
 filename="brin-bench.ods"

UEsDBBQAAAgAAOO7Q1KFbDmKLgAAAC4AAAAIAAAAbWltZXR5cGVhcHBsaWNhdGlvbi92bmQu
b2FzaXMub3BlbmRvY3VtZW50LnNwcmVhZHNoZWV0UEsDBBQAAAgAAOO7Q1IAAAAAAAAAAAAA
AAAcAAAAQ29uZmlndXJhdGlvbnMyL2FjY2VsZXJhdG9yL1BLAwQUAAAIAADju0NSAAAAAAAA
AAAAAAAAHwAAAENvbmZpZ3VyYXRpb25zMi9pbWFnZXMvQml0bWFwcy9QSwMEFAAACAAA47tD
UgAAAAAAAAAAAAAAABgAAABDb25maWd1cmF0aW9uczIvdG9vbGJhci9QSwMEFAAACAAA47tD
UgAAAAAAAAAAAAAAABgAAABDb25maWd1cmF0aW9uczIvZmxvYXRlci9QSwMEFAAACAAA47tD
UgAAAAAAAAAAAAAAABoAAABDb25maWd1cmF0aW9uczIvcG9wdXBtZW51L1BLAwQUAAAIAADj
u0NSAAAAAAAAAAAAAAAAGAAAAENvbmZpZ3VyYXRpb25zMi9tZW51YmFyL1BLAwQUAAAIAADj
u0NSAAAAAAAAAAAAAAAAGgAAAENvbmZpZ3VyYXRpb25zMi90b29scGFuZWwvUEsDBBQAAAgA
AOO7Q1IAAAAAAAAAAAAAAAAaAAAAQ29uZmlndXJhdGlvbnMyL3N0YXR1c2Jhci9QSwMEFAAA
CAAA47tDUgAAAAAAAAAAAAAAABwAAABDb25maWd1cmF0aW9uczIvcHJvZ3Jlc3NiYXIvUEsD
BBQACAgIAOO7Q1IAAAAAAAAAAAAAAAAMAAAAbWFuaWZlc3QucmRmzZPNboMwEITvPIVlzthA
LwUFcijKuWqfwDWGWAUv8poS3r6Ok1ZRpKrqn9TjrkYz3460m+1hHMiLsqjBVDRjKSXKSGi1
6Ss6uy65pds62ti2Kx+aHfFqg6WfKrp3bio5X5aFLTcMbM+zoih4mvM8T7wiwdU4cUgMxrSO
CAkejUJp9eR8GjnO4glmV1F066CQefcgPYvdOqmgsgphtlK9h7YgkYFAjQlMyoR0gxy6TkvF
M5bzUTnBoe3ix2C904OiPGDwK47P2N6IDKblXuC9sO5cg998lWh67mN6ddPF8d8jlGCcMu5P
6rs7ef/n/i7P/xnir7R2RGxAzqNn+pDntPIfVUevUEsHCLT3aNIFAQAAgwMAAFBLAwQUAAgI
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
qj3ilyQOPhr0ABLtL3rhZyov0EILLbTQQgsttND+W1rqv9n/cfyPtLu9/1v//Op6vYEY/1mt
W6p3rm9s+rFGaz8x2MF6O6wN/SU0Y2o3tvDifH1Jv4qU7vqardljWAZb3pyj1Tq6spysn/fd
2kTWub1a2+VJvKrVtXjeoiYdYprGsV9fxoqz3RtNUinHrl0haYvWpK6ELiWP4mOcD1bNUlgn
6uNKr69UXetjCoGnpsaut8D1spZC5LSaHJ0d1czXz8RDc7d5Xl9JkXeLGk6noLyv069jXdNk
vHUxiHZKk/clm/mSVvMxB7N+Wwrb+ur8Rl5vV7WKquUlh2kYw5Hzcn1uJ5KV344XmvjGZUpE
Stoq+wVtm/1QsoBjNO341mdqLcsKuza3xemjv4aNbm0aIxcZr6vahaTTlXfDKXC0/hPnbbIh
dLuFtK3JJRedK9LWwkv4dazpvPpsU+lmWzg6OQPk79IYL24UG9bslrl36/rubP6q+62s5Pf9
wHc1PnlNpg9l0CfL+PFzjx2XGxkfGnh7uNz5iO/djLTU957HpfBBL+pD0eqTRd9D7o/6e7y+
FvihAf0zWF0OlqCfvepL4Vohc/xLuiQb8JEHU5ZKK8zje+XvT6sPycePmnz4Ht4L/c7BjvxQ
okqyG1PpV7RJyfVaJ3XoNLfogiEllSAVaYLorhsnctwrZOQlenur3985r7+vxDrOVa7h5t79
g2aV7QOJ5jA3Zp3MfkE78spr5nXxXL0erGVDloocPvFtUd4Zmr3e9SJbgfZzf8nBurVNy3Qo
ye30uaENTd1KTi2JhPxyNutjV2NFaXsgTNKB5lK9tJLLyr5x1OeWrIjnTVJcK7mhyCW72Fil
RVKxeefJNrbtTDT4diYsRe0z70dtfGYwi2RAEm5b7UfOj82tm6eHlvLEeapzuaI957ZIJuBl
gM4pTefcynGfv+dXGCXispx2WSvuXdu8BEn6K6f8lk5tdzJYkhnObZP1/Nj3xHPwzGNa+Sog
s/Zr7b7Z3nVVh6qmhiXLeVvlkNdkzlZiYLWrbqpApuj7RLfd5Dy/acdUJWViard6qGJL9HmW
JnV9bG7H1LflgTDpfshB1wvavEn22sPOR5AlmSP9rHDmvp8P8kI+nxX5WC2UIh2V25Hlo+fZ
MrZt2+/VEs/L1vHg3PIeHhmmXbofb0eC/RZaaKGFFlpooYUWWmihhRZaaKGFFlpooYUWWmih
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
--------------4B194FF8F3EA3786FF9EAE1F
Content-Type: application/x-compressed-tar;
 name="brin-stress-test.tgz"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
 filename="brin-stress-test.tgz"

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
4sSJE/vk/y10LU4AkAEA
--------------4B194FF8F3EA3786FF9EAE1F
Content-Type: application/x-compressed-tar;
 name="brin-bench.tgz"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
 filename="brin-bench.tgz"

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
--------------4B194FF8F3EA3786FF9EAE1F--





^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/9] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 4e0c9be58c..4099e72001 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8191,7 +8191,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------0E72B707603BED22B4040825--





^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/9] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 1487710d59..33841e14f2 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8191,7 +8191,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------22A4B241170149838D4D1F8F
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210215.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210215.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 58fe109d2d..8a1a9da78f 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -389,6 +389,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -410,6 +413,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -470,7 +528,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -480,51 +538,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index d7b55f57ea..871e024e00 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8143,7 +8143,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8159,7 +8159,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------CF71AF65F7C337C37C24B045
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210112.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210112.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/6] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 58fe109d2d..8a1a9da78f 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -389,6 +389,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -410,6 +413,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -470,7 +528,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -480,51 +538,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index d7b55f57ea..871e024e00 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8143,7 +8143,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8159,7 +8159,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------D21F32E0F9E7408E9BE1AF2E
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210114.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210114.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/6] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index d27336adcd..f3ead7d53d 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8145,7 +8145,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8161,7 +8161,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------310A2AE1CC4C2E2E77559E3D
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-suppo-20210114-2.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-suppo-20210114-2.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index b5f52d4e4a..2ef11245a8 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8183,7 +8183,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8199,7 +8199,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------FA974B75A0C3E9CA18CE7207
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210122.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210122.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/6] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 158 ++++++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 140 ++++++++++++++------
 src/backend/access/brin/brin_minmax.c    |  92 ++++++++++---
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 303 insertions(+), 95 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..963b7079cf 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,78 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of
+					 * multiple scan keys. We can determine that based on the
+					 * number of arguments - functions with extra parameter
+					 * (number of scan keys) do support this, otherwise we
+					 * have to simply pass the scan keys one by one, as
+					 * before.
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same
+						 * for all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet
+						 * the criteria for a single one of them is enough to
+						 * discard the range as a whole, so break out of the
+						 * loop as soon as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+
+							/* mismatching key, no need to look further  */
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..a260074c91 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -251,6 +253,10 @@ brin_inclusion_add_value(PG_FUNCTION_ARGS)
 /*
  * BRIN inclusion consistent function
  *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
+ *
  * All of the strategies are optional.
  */
 Datum
@@ -258,24 +264,31 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/* Handle IS NULL/IS NOT NULL tests */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -284,7 +297,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -293,7 +311,14 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
@@ -301,10 +326,45 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all regular scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* Skip IS NULL/IS NOT NULL keys (already handled above). */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
+	/* This should be called only for regular keys, not for IS [NOT] NULL. */
+	Assert(!(key->sk_flags & SK_ISNULL));
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +384,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +444,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +464,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +483,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +518,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +528,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..e116084a02 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -140,29 +142,41 @@ brin_minmax_add_value(PG_FUNCTION_ARGS)
  * Given an index tuple corresponding to a certain page range and a scan key,
  * return whether the scan key is consistent with the index tuple's min/max
  * values.  Return true if so, false otherwise.
+ *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
  */
 Datum
 brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
 	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -171,7 +185,12 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -180,13 +199,52 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
+	}
+
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
+
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +287,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 1487710d59..33841e14f2 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8191,7 +8191,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------6A37408A2C42B5B56C3B3D49
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210303.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210303.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c          | 158 +++++++++++++++++++-----
 src/backend/access/brin/brin_validate.c |   4 +-
 2 files changed, 126 insertions(+), 36 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..963b7079cf 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,78 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of
+					 * multiple scan keys. We can determine that based on the
+					 * number of arguments - functions with extra parameter
+					 * (number of scan keys) do support this, otherwise we
+					 * have to simply pass the scan keys one by one, as
+					 * before.
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same
+						 * for all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet
+						 * the criteria for a single one of them is enough to
+						 * discard the range as a whole, so break out of the
+						 * loop as soon as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+
+							/* mismatching key, no need to look further  */
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-- 
2.26.2


--------------AC3FFB734F56C5F52D422EFC
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Process-all-scan-keys-in-existing-BRIN-opcl-20210305.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Process-all-scan-keys-in-existing-BRIN-opcl-20210305.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c          | 158 +++++++++++++++++++-----
 src/backend/access/brin/brin_validate.c |   4 +-
 2 files changed, 126 insertions(+), 36 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..f9a0476024 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,78 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any scan keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of
+					 * multiple scan keys. We can determine that based on the
+					 * number of arguments - functions with extra parameter
+					 * (number of scan keys) do support this, otherwise we
+					 * have to simply pass the scan keys one by one, as
+					 * before.
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same
+						 * for all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet
+						 * the criteria for a single one of them is enough to
+						 * discard the range as a whole, so break out of the
+						 * loop as soon as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+
+							/* mismatching key, no need to look further  */
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-- 
2.26.2


--------------82D677E9F94AC7574E460205
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Process-all-scan-keys-in-existing-BRIN-opcl-20210308.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Process-all-scan-keys-in-existing-BRIN-opcl-20210308.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c          | 158 +++++++++++++++++++-----
 src/backend/access/brin/brin_validate.c |   4 +-
 2 files changed, 126 insertions(+), 36 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..f9a0476024 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,78 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any scan keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of
+					 * multiple scan keys. We can determine that based on the
+					 * number of arguments - functions with extra parameter
+					 * (number of scan keys) do support this, otherwise we
+					 * have to simply pass the scan keys one by one, as
+					 * before.
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same
+						 * for all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet
+						 * the criteria for a single one of them is enough to
+						 * discard the range as a whole, so break out of the
+						 * loop as soon as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+
+							/* mismatching key, no need to look further  */
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-- 
2.26.2


--------------556A1DC61262AF15641DB204
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Process-all-scan-keys-in-existing-BRIN-opc-20210308b.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Process-all-scan-keys-in-existing-BRIN-opc-20210308b.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow future opclases to benefit from seeing all keys at once.

This does break existing BRIN opclasses, because the signature of the
consistent function changed. We might support both variants (with 3 and
4 parameters), but that seems pointless - the changes to NULL handling
likely require updates too. So better to make the failure clear. Also,
we're not aware of any out-of-core opclasses - there may be some, but
probably not many.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 doc/src/sgml/brin.sgml                   |   8 +-
 src/backend/access/brin/brin.c           | 118 +++++++++++++------
 src/backend/access/brin/brin_inclusion.c | 140 ++++++++++++++++-------
 src/backend/access/brin/brin_minmax.c    |  92 ++++++++++++---
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 6 files changed, 269 insertions(+), 97 deletions(-)

diff --git a/doc/src/sgml/brin.sgml b/doc/src/sgml/brin.sgml
index 06880c0f7b..078f51bb55 100644
--- a/doc/src/sgml/brin.sgml
+++ b/doc/src/sgml/brin.sgml
@@ -464,12 +464,14 @@ typedef struct BrinOpcInfo
 
    <varlistentry>
     <term><function>bool consistent(BrinDesc *bdesc, BrinValues *column,
-       ScanKey key)</function></term>
+       ScanKey *keys, int nkeys)</function></term>
     <listitem>
      <para>
-      Returns whether the ScanKey is consistent with the given indexed
-      values for a range.
+      Returns whether all the ScanKey entries are consistent with the given
+      indexed values for a range.
       The attribute number to use is passed as part of the scan key.
+      Multiple scan keys for the same attribute may be passed at once, the
+      number of entries is determined by the <literal>nkeys</literal> parameter.
      </para>
     </listitem>
    </varlistentry>
diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..743f2a925a 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,40 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
+					Oid			collation;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
-
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
-
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					/* skip attributes without any scan keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
+
+					bval = &dtup->bt_columns[attno - 1];
+
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * XXX We simply use the collation from the first key (it
+					 * has to be the same for all keys for the same attribue).
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
+					collation = keys[attno - 1][0]->sk_collation;
+
+					/* Check all keys at once */
+					add = FunctionCall4Coll(&consistentFn[attno - 1],
+											collation,
 											PointerGetDatum(bdesc),
 											PointerGetDatum(bval),
-											PointerGetDatum(key));
+											PointerGetDatum(keys[attno - 1]),
+											Int32GetDatum(nkeys[attno - 1]));
 					addrange = DatumGetBool(add);
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..a260074c91 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -251,6 +253,10 @@ brin_inclusion_add_value(PG_FUNCTION_ARGS)
 /*
  * BRIN inclusion consistent function
  *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
+ *
  * All of the strategies are optional.
  */
 Datum
@@ -258,24 +264,31 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/* Handle IS NULL/IS NOT NULL tests */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -284,7 +297,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -293,7 +311,14 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
@@ -301,10 +326,45 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all regular scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* Skip IS NULL/IS NOT NULL keys (already handled above). */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
+	/* This should be called only for regular keys, not for IS [NOT] NULL. */
+	Assert(!(key->sk_flags & SK_ISNULL));
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +384,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +444,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +464,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +483,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +518,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +528,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..e116084a02 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -140,29 +142,41 @@ brin_minmax_add_value(PG_FUNCTION_ARGS)
  * Given an index tuple corresponding to a certain page range and a scan key,
  * return whether the scan key is consistent with the index tuple's min/max
  * values.  Return true if so, false otherwise.
+ *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
  */
 Datum
 brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
 	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -171,7 +185,12 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -180,13 +199,52 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
+	}
+
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
+
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +287,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..2c4f9a3eff 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											4, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index c7619f8cd3..cd1eda38ab 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8223,7 +8223,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------D524CD37E77B36A2883A7617
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Move-IS-NOT-NULL-handling-from-BRIN-support-20210311.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Move-IS-NOT-NULL-handling-from-BRIN-support-20210311.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/9] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 4e0c9be58c..4099e72001 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8191,7 +8191,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------4B194FF8F3EA3786FF9EAE1F
Content-Type: application/vnd.oasis.opendocument.spreadsheet;
 name="brin-bench.ods"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
 filename="brin-bench.ods"

UEsDBBQAAAgAAOO7Q1KFbDmKLgAAAC4AAAAIAAAAbWltZXR5cGVhcHBsaWNhdGlvbi92bmQu
b2FzaXMub3BlbmRvY3VtZW50LnNwcmVhZHNoZWV0UEsDBBQAAAgAAOO7Q1IAAAAAAAAAAAAA
AAAcAAAAQ29uZmlndXJhdGlvbnMyL2FjY2VsZXJhdG9yL1BLAwQUAAAIAADju0NSAAAAAAAA
AAAAAAAAHwAAAENvbmZpZ3VyYXRpb25zMi9pbWFnZXMvQml0bWFwcy9QSwMEFAAACAAA47tD
UgAAAAAAAAAAAAAAABgAAABDb25maWd1cmF0aW9uczIvdG9vbGJhci9QSwMEFAAACAAA47tD
UgAAAAAAAAAAAAAAABgAAABDb25maWd1cmF0aW9uczIvZmxvYXRlci9QSwMEFAAACAAA47tD
UgAAAAAAAAAAAAAAABoAAABDb25maWd1cmF0aW9uczIvcG9wdXBtZW51L1BLAwQUAAAIAADj
u0NSAAAAAAAAAAAAAAAAGAAAAENvbmZpZ3VyYXRpb25zMi9tZW51YmFyL1BLAwQUAAAIAADj
u0NSAAAAAAAAAAAAAAAAGgAAAENvbmZpZ3VyYXRpb25zMi90b29scGFuZWwvUEsDBBQAAAgA
AOO7Q1IAAAAAAAAAAAAAAAAaAAAAQ29uZmlndXJhdGlvbnMyL3N0YXR1c2Jhci9QSwMEFAAA
CAAA47tDUgAAAAAAAAAAAAAAABwAAABDb25maWd1cmF0aW9uczIvcHJvZ3Jlc3NiYXIvUEsD
BBQACAgIAOO7Q1IAAAAAAAAAAAAAAAAMAAAAbWFuaWZlc3QucmRmzZPNboMwEITvPIVlzthA
LwUFcijKuWqfwDWGWAUv8poS3r6Ok1ZRpKrqn9TjrkYz3460m+1hHMiLsqjBVDRjKSXKSGi1
6Ss6uy65pds62ti2Kx+aHfFqg6WfKrp3bio5X5aFLTcMbM+zoih4mvM8T7wiwdU4cUgMxrSO
CAkejUJp9eR8GjnO4glmV1F066CQefcgPYvdOqmgsgphtlK9h7YgkYFAjQlMyoR0gxy6TkvF
M5bzUTnBoe3ix2C904OiPGDwK47P2N6IDKblXuC9sO5cg998lWh67mN6ddPF8d8jlGCcMu5P
6rs7ef/n/i7P/xnir7R2RGxAzqNn+pDntPIfVUevUEsHCLT3aNIFAQAAgwMAAFBLAwQUAAgI
CADju0NSAAAAAAAAAAAAAAAACAAAAG1ldGEueG1sjZJNb9QwEIbv/IrI9JqM87EfsbKuxIFT
EUgsErdV1p4Gg9de2U6z/HvyTVt64JZ555nxvJOp7m8XHT2h88qaA0kTSiI0wkplmgP5dvwY
78k9f1fZx0clkEkr2guaEF8w1FFfajxrnJT6QH6EcGUAXdclXZ5Y10BGaQ4NyDrU8ZPC7j2Z
K4biA2mdYbb2yjNTX9CzIJi9olmeYH9ZNo41xTetzK+3XkvLsoQxu6BSrNy1dXqkpADUOPT3
kCYpLKy1doWHKSa/i40Cpnilx+h/Lcy7G03M388WnhG+bHfwyqvRcYMGXR2s4w/q7PDzCMA2
KZJdkt09KNPeTt/329O2iJ4Bp6uzP1EEKOjdh1ZpGWcVvOpXScH6X4I8o1ka0yymxZFSlqeM
bpJyX+ab3S4vK1iwaR6UKvQnEcu279JPzr8c80/br3P3f7Ivi8RvodHz9BU9yxO7XpYPfQsf
lIhGPdRnjbGwrQn9tsgkCtR61TYZ3cy6PQ/ulwwlwCt4sVt46475H1BLBwhD5qoIhAEAAAUD
AABQSwMEFAAICAgA47tDUgAAAAAAAAAAAAAAAAoAAABzdHlsZXMueG1s7Vxtb9s4Ev5+v8Jw
cYsWWEXyWxJ7Exd71929Bdpg0XbvPhaMRMnclUSBouKkv/6GlKh3ybIiv6SoEzQVORzOPDMc
DimTN28fPXf0gFlIqH87nlwY4xH2TWoR37kd//n5V+16/Hb9jxtq28TEK4uakYd9roX8ycXh
CBr74SpgOIRCxCWPiPkrikISrnzk4XDFzRUNsK+arqptVrLbuNwMwxm/HW84D1a6vt1uL7az
C8oc/fNHXdRpHD9yPaXeIMa7dimJ832FD07XtkCqmdQLQN57F+eZWAxtu3IRtABsvjkLMm1F
ixhoqfHUMBY6wwFlXFEL5bt2JmgL2gqTddZXEOdbe5ijro0Fbb7to0v8v+tsOlkul7qsTUk3
3HObSUWtIrVpV3keQ1ezaYP9qN2VDbWh3TS1u5mKGUTMlUJapo5dLJqE+uRikrqpwyyrVisw
8UyHdogj7YHg7atUKkpb3GKux8+ZD86s7j44swoDDrlm5lXMSce4TSPfisdnzA8/BpgRUYVc
2WxV4FAeFK0qTAxd0KS2JNhVGqSkdd0CU80LNeJzzGiwyrUu2lS0725X2VuuPUf33YeKJM63
9iPvHrPO9gDbV0YbqLlttf+WEUAgR262kgsTFZRr96+lLolUC5f2cJAE1RyHQjhBfNMwzK/1
D1Ap//nwPhvszOuKqKAtBD6TkaBz2IypC85MvYaxO9GBQsMPYsCPR4nGucl0Ol6rmdOmMGva
yMSahU03XN/ENk+LR/GzkOx2/DMjCOIcTDqKwCPukyrX2xu/J+B90iyjT8gPa9j8gAIa/lSi
iwvHowJrQa852AezgoOFWxKGBYqAcBPs+IBAMOEwO0R7h/9C/43axcrRdBHpKeTYe5ZMjBJL
djd6hx+Qjxxo2CxdHfVR5HxP/OhxJI3GiY9Hv7UYtkQ5mHx6kzMn5XFWqPSwsI0iN8kVFedE
UhlfNBO77liRB4ghh6FgowUQ2oXskGDGVUANXGigWSTkyBeh3bhYED/DTCQ71XZSzoZRYdOV
i3wnQg7UYl8WmBDROAPx/vw0LrPQIHIgv+zDkkbxUSRfN6omYagq/n1XZSuyEhc/tjNOiTak
zDqt+v1OmqgG+/VNPCUlM1PBIDE6d8a4RDRKnjziy9nWgXYWcQgPIbDJjmp4pjw4zAJ13Uym
k6wjYB1xsFXymOSnLvUdwV9xAsOuV2lv8lHVhdikvtXEQK/I0kE8SO8UDYt8E3GsUV+jENNt
V0zJNnJDnKmwoRELuwl7jtrOjmMMVQbBgnjI1QIXQkfZj2oEb3bXyXSeiR6aBCZgAhFIK/pu
tb9RnIgIp66pbHX5fC0kOtQXy+Bcdcw5rZEZ6gOCrH+m6iAvMbGVNQ6JAzEB/AzvHE9mxBgs
y59qsTDAbf8wVFx4oC6EOYG95KzELsY6xTYX72r6evLuqas3BIYyfkYbuEZHcB1Go0BuPShY
8q42KnmeXotOd9B6gCM7fl0/As4XuDclgWMoPBSkc4lvkXj3Blw2wq/f/ODwn25Tn0JB4CYw
aiWv059thtl33+0B2j7g1KdIMt9xKSxUX9m2AZ+yyN/dPHPQ57v54vRuPm0zwfQc3XxxHiH6
CMAdyHcXg/ju5Xff7QHaiwvRL9fNLzu5uSWWcw3Wuurhyh4s4jclBfV6i1joqRvhE0apfRqW
eJkanTS77qFZVVytYVUrIBjlaiKx5KmzfAMDoW9/3Zan062fxDOjr58dFuTGPQIQedJD5INs
jJQDdPKAPC3wem6BgHp9loHns+9zeHz2WmoMjU9Pmecv2qYtSreFlj7J8pGnsA7eOrjr1ES7
+E8TjlcDZrvtCdcJ9x3yEHTF5XQJ7clhPEzeKl1t195vu1GWR3PWE67A+uByrs76YhdZ0tWe
5azzQbZ6Y/SUv+SekhqbuK4mvuuHTI5ZRlMqP5vQMpzTA76Ts8P3RYX1Z2E/PU/stb0cTAbB
JhX77sY2pHqyLwhGHPt8x6DoFsJ2RLB5spPfgZnbhdmkG7NdgVW6Tj7tT03Qda9xPmTKWt08
/Lbiar/tXIB4gNg6LMQvMrT2hn+A8HoA+Buja4OebfG1zx70WcXXqyHj69Vg8fVqZ3xtndoX
kxeXtr6otRrg+y2lrSdY4D0L+3NNW488r1VW90OlzYs+70/OKazL+DdUWJeDfZCwLl33WWnz
4rDfyfm24nq/vA0g/obS5hOG9t7wn2nafK7Rff+0fdH7S2rnEt8XQ8b3xWDxfdEc3+N2VXu8
i4+9pKdsmk8bZUXVY0OMxufSNeTKr+j71MfpKBKUJvhdUndPOade80Gk3EsEQ34qJ4DS435A
WnPar+kcUt15sIwyOd+V0PY9F6baN50OU/XpGbHm001VZZKuShTZEaYdpv4PRuKSghZTJzUB
YumNBVrRTfYwmjJOSL4Cg+k84LkywUS4CfPydtxi4my4cBHX2luvL1PjSzpzWiSEMPekFShG
k166K9x66z653kP3pLyP9tN27acn0n56QO0/gzTPcmi9mfcd5bgXbylUe9gEve+R+bfIbHxL
y16a2rZpZlZEDvUhcN67GmfFoJrWcahO6wRXyixxlN64uIIRNwqpS6zRq2tD/HSKuTP5qRjR
OKARf6WU+8OA3axXAkEXvQiHqcocYGg+gRzxXR0HVEyMOYz3MliOJ7iflBErGukxDSRbYolL
CFDEaQNFk1B9IfwEeUUUHmqE/0ap1Yt3IlafMW6acox3S38uL2vi6SGH4h2OOMulHUcCJQl8
XUBZLo8Oyr/Q0b1EwNERENOsnXUPCcj/EPP7ZpJlUM5KsV8Yo+z4EUF9VWonJLb8PAuS/XLr
n00TND3NkuHgarWsGGKCnguGBLQ+vpAgcSRf2Hd4ZLA1LDUS2PqtNJ4B2x757Ulhm7XCNjs2
bJb8dFfkIw7b94qOHQ1Upn6chDYvVHvc0UvX+ySPoh8PcWJqqkLh5WAN3IFGvID3h8CbjGuI
au7tISyEYkESb/7djsV+KPGjdFUlLkCDSVvzqAWsXabx+2zAbGCVn72iK5TZsDqDP0VbiR3j
TQKBcTFdLmYkvhDIQ8yBOhfboqZYyBL6Ymm8HyjYGMvreXxFkd4sVSLOKSTlNKgVsyiSXjFX
BzNPu5n5xdgwvxUxvZgvs62I3EAKkBXfmgrNjKuJalaTIRniJ4UoR0E8gKviMBV1X4ZHnSto
A/j3rJt/Q+zSxGWEiMv3f0kLRiDgUkayG3PFDa8MEV6D5fJ6tmxyzmpdYquLq/l1vb1UTV4U
qUJiJw4jsHsMDk0EMyKnYjoz/tkWmfMdAh9xEW84Sm7DDUf0/i9sQsFXzKgm3w6F5xkHvsFY
rjdO5kmFh8KURTrFJ4WCU9v7t/zoqMkBYnDWNyJJWQXJ33CDcUy9fvv27Y1eLkxKgpIpSoAL
7IrJqbq7TS+aK+39D6FL8pA5/Xqi+suVVURQrAqgt4qgV3DcBe3H5CLoFmSnFWTjJ4Yd8TZT
CLQv2HGBvn4d/48T7uZJ4+c3FUAKPRaKpP+WpBAnNBVS4ibkfKZ9B6uvlCgODjCdGNOJZkw1
Yz5eG4Yufw0jkUIQrn8cKYG93azlOduEtWGsplerxfLicnYpDj9Pr0UXK/mbKl3nhkX9Tueb
ymJ6voH8DsJ6ucw3iMtO4stCn0/i+cvC/vJJuFvDxkVGWKSqdf9Zyf13YLyvNToR7Y+UXh9n
9fob99f/B1BLBwgikX6e1QoAALFfAABQSwMEFAAICAgA47tDUgAAAAAAAAAAAAAAAAsAAABj
b250ZW50LnhtbOzdXa+byBkH8Pt+Cssr9Y7Y+AWDm2RVadXeJFXVbKverYaZZ2w2GCzAxyf7
6TuDDcav+2yOzzmZ9J+LJIYZGGD4Mdj87bc/Pq7S3gMVZZJn7/r+m2G/R5nMVZIt3vX//fPf
vLD/4/s/vc21TiTNVS43K8oqT+ZZZf7tmdpZOV8XVJpXoqoXsimyeS7KpJxnYkXlvJLzfE1Z
U3d+Xmder3c3XZbluHrXX1bVej4YbLfbN9vxm7xYDH7+18DO8yp6rAZN6UWhVHqp9Gg4HA8W
AyUq4T0ktP2hqfG4rFYXa/hRFA3quW3RMrmyaH/w348fPsklrYSXZGUlMkntBixFUXH3Ql24
u/nlw4Jb1xQ1x2G1NrswTqm7EFWILXcptqw52N3qxfpwAGyN3cFvtn06KGidF1VT2h4P7sps
2aOtrb6kxN5eW7hbe0WV4Fa2Zbt1H9Mk+3y9G9i5TVGdc1fyWKaezq8clFxzF5NrU2/UHkzZ
NnO9KdK6kUoOKCVbpRz4b/z2dMjz/MaRmwx2rw/dZKz43WSsuluj82L1uK/crmi/BHpcU5HY
yiI1TTIVvFxpc6JUVOTr+WEBR+e9SOWhJxWL1hqdbzK1Y+LC4m21+dESTk+Em/vEHw5smXar
EkoVb6tyb1WebpKtfXzIbX3+Ya/X1qlfiZh/etSFu7WzzSqmgn2AjZRnZ5jZzO3NDrUtErMH
OsXlzeL2EB1t3O0OGw3qQk2NNP+KDrLfq50lHBEiquUVBcLBRzOz/uvjh2635+7R0x5eyiJZ
s6nclT7qzPnq6uXInmP0YD1ogbOrL69UGA12sw9XOvX7V7p+b78vO8OFUf99MzbYNbgctBO0
GSN4WkjyFMm0fP92173ayb3da7sT3vX/WiTCXHjNNa0psErSL830we3KHxLT0ese0PsksvLC
Yv4s1nn5l5Nyu4n93tGibXlvQZnpQaYvl9ukLI9KrJNKmi7zIEzDbN/8nab9RL+K/2xuN6tT
htOkL2VFqye1qcgTVa+u9xM9iEwsTMXrrbtU+kXa+SHJNo+9+qBVSUa9v984sCcl79a+wbXO
vJ8uNlVuEEmkVy+n7eX130dbI3O/Xdm+8bVuZriQblZZv6nZneitzdXFbhOVPZ3P44LEZy8m
c+6aBdpVN0vcF98mynpmhgT+eJJk9QZ02nO9ccW1xhX59qRlZkq3WbtZduKSksXS+DZ840f+
zKz9dpM3JXn5ukpWIvW61atiQ3+k4aM7NtwMCIIXa/j4ng33w+irG65FWv6Bllficl9pJq7M
OIIKby0W5O1q/NP895Od98tU//JpSVT5J5vY2bzdOEYl5ToVX/Z7db9kO9ow9yreKldmqWnh
VfF5s3fDnv3oxztv/j8m/ZNCvf0rc2bX+8asWJK5dJqetRswrJLMuzBzX83OtQPBhVmdShZJ
Zeb67dxFkW/W9d102z8utLBtkb1DutRofzjsHxfa34J3Fnioe0MhuqYQpWkzZy0Ke5Nfv/Ca
65gWm7Q6VcpUOu+adTtEmiwyr8w3hR0BP4h0Q171Zd0eS3MTSaLdiqYT2g68LcS67qd2iJHl
nn3d1FJJQXI3J62Kdln57n0ET2QLO2Aens+wrbFLy9oGlMvC3OR5Ve7p5LD+3bwHuz1msNrU
i/PKMN90h3bur5uySvSX/VnWXs3M7hML0+hld9fU72vsds1xNbvJK1EsTC9KSduz2Z7Ilzq8
PaMOa6kXdXx9MFeB3Az4fxjWf/rdw5FvKnNPSyfbWc+y071qafrpYunt78i7O+q8kD2Ox2Xq
y+PRSM40p55YJr+Zib6/rjrTmpUUq33RXdddCmXvN85Wbsb3VNQtOGpes7jt3rFmeZ0m2bV7
ZqwtsqYN3Zl1/97PvVB5t9wbBewG13f7KT0ehrAna2/nX1l/O/96C06LsKmWdOXqeJez3V5s
8sIcGm93ftgL0Wyyrnplnpoh40k3VIlY5Jk5a+LUq4rjo9zOq8zs4kIPuLcmh6bvzrnjxhwb
cyhbNP3sUPiO9BzWU+Xr4wrwCB59Hx5dGfQ+7+hDJ4//r8OOpi/vl0iZ6uPUx6n/Gqf+BEMR
zlDkdsMxNIFP8OlZfJq+qE8XzXm6R08Y6gAiDJ6A0zeKU/AknJqz1j4N1Z2/f1v5q26q8JYu
KAAFr0DB7LUowE3WdzS2AV7A6xXwCoEXPqwCVsDKBawiYPWyWN3aSuAFvIAXHy9/+Fp6XdXl
Hm9O3xbl7lQ8mwon7y1LyuogDbAAFq+BhT98pjuzyVd+MmanC/nZPj6dKa/psmEgScTPMPDB
52b43AywfZewPdNd3J1hmxnYJGADbIANsLFge64bvDvDFquhwJNOgA2wATYmbE+LqL4UbEr5
8XO8Bw/YABtg+y5he1oa94Vgm+qYQg3YABtgA2w82J4W630h2IJhTBFGbIANsAE2JmxPCy2/
HGwasAE2wAbYuLA9Le38Uu+xDWUsZoANsAE2wMaD7ZmS0veFbaYNbAFgA2yADbDxYHum3Ped
R2wjKUUI2AAbYANsPNjcSB5MpRICsAE2wAbYeLA5kTyYyliFCrABNsAG2FiwjZxIHtSwneMF
2AAbYANsF2FzInkwIynEFLABNsAG2HiwOZE8mMUyEmPABtgAG2DjweZE8iD0pcRzbIANsAE2
LmxOJA+mMT48AGyADbDxYXMieTAVsQzxfWyADbABNiZsTiQPBCmSSB4ANsAG2JiwOZE8iGfk
S4zYABtgA2xM2JxIHsQhjSTeYwNsgA2wMWFzInkghzRVeNwDsAE2wMaDbexE8iCQchwhBA/Y
ABtgY8LmRPIg0HIa4ef3ABtgA2xM2JxIHgRKTqIIsAE2wAbYeLA5kTyY+WbEhk9FARtgA2xM
2JxIHghfRfE5XoANsAE2wHYRNieSB2KqhMSPuQA2wAbYmLC5kTwIVSxHgA2wATbAxoPNieRB
MJN+hO9jA2yADbAxYXMieRCEchQhKwrYABtgY8LmRPIgiAAbYANsgI0N28SJ5EGkVRjjcQ/A
BtgAGxM2J5IH9eMeCMEDNsAG2JiwOZE8iIQKYiQPABtgA2xM2JxIHoixGbFpwAbYABtg48Hm
RPIgCKQfTQAbYANsgI0HmxPJAy1oQnhAF7ABNsDGhM2J5IGBbUw+YANsgA2w8WBzInlAgZ7S
OV6ADbABNsB2ETYnkgc01mPCF00CNsAG2JiwOZE80PUfwAbYABtgY8E2dSJ5YFRTGg/oAjbA
BtiYsDmRPNAxTQmPewA2wAbYmLA5kTzQwsCGn98DbIANsDFhcyJ5QFM9IdyKAjbABtiYsDmR
PKChHpEAbIANsAE2HmxOJA+IdKhxKwrYABtgY8LmRPKAtIENHx4ANsAG2JiwOZE80DEF+FQU
sAE2wMaFzY3kwURPCN+gC9gAG2BjwuZE8qD+8ABfNAnYABtg48EWOJE8IKEDjR9MBmyADbAx
YXMieUChnhKyooANsAE2JmxOJA/CQJLAc2yADbABNiZsTiQPwkhqgeQBYANsgI0JmxPJgynF
5m4UsAE2wAbYeLA5kTyY6pgifHgA2AAbYGPC5kTyYKpiFZ7jBdgAG2ADbBdhcyJ5YG5FARtg
A2yAjQ2bE8mDGclYTAEbYANsgI0HmxPJgzCUWiBSBdgAG2DjwTZzInkQjqQUM8AG2AAbYOPB
5kTyYBrHMsRzbIANsAE2JmxOJA+EUFLiiyYBG2ADbEzYnEgexL7SMgRsgA2wATYebE4kD+IR
DSWyooANsAE2JmxOJA/iiEYSz7EBNsAG2JiwOZE8CIQcR/hUFLABNsDGhM2J5EFAchLhVhSw
ATbAxoTNieRBoA1sMWADbIANsPFgcyJ5UD/ugV+pAmyADbDxYAudSB6IiRIxvo8NsAE2wMaE
zYnkgRiqMEbyALABNsDGhM2J5EE8Ulri5/cAG2ADbEzYnEgeiJGKYjzHBtgAG2BjwuZE8iAI
pB/h+9gAG2ADbEzYnEgeBCFgA2yADbDxYXMieUAzPSXcigI2wAbYmLA5kTwgpWd6BNgAG2AD
bDzYnEgeaEETwvexATbABtiYsDmRPNBaS43fPABsgA2w8WA7/AzxNw2bWZ1GCB6wATbAxoTN
ieSBGbHFgA2wATbAxoXNieSBiJVCCB6wATbAxoXNjeSBNLDhOTbABtgAGxM2J5IHIlRS4nEP
wAbYABsTNieSB1pohU9FARtgA2xc2JxIHkSBmsQBYANsgA2w8WBzInkQTQ1seI8NsAE2wMaE
zYnkgfTJjNkAG2ADbICNB5sbyQNfRxojNsAG2AAbC7bRoSN8y7BRqAPCbx4ANsAG2JiwOZE8
mEkZidcJwf8PAAD//+zdu20DORSG0Zash6VhORw++i9hx0o2sIMbLfYHTgVKhANyyI8XbGAD
WyBsEeVBu8/HCTawgQ1sRdgiyoPd5piGuYANbGArwhZRHlywzWkSPNjABrYibBnlwTFf01YU
bGADWxG2iPLggq1N5QHYwAa2ImwR5cHnoUnf2MAGNrAVYYsoD/b2gi7YwAa2OmwZ5cG5+rJi
AxvYwFaD7RZRHuw21/RsEdjABrYibBHlwedUVAQPNrCBrQhbRHlwwdbnG2xgAxvYarBllAdr
HxtsYAMb2IqwZZQHY53LqSjYwAa2ImwZ5cFYe/3GC2xgAxvY/oQtozxoe2ytKNjABrYibBHl
wXms+7BiAxvYwFaELaI8WL3dDt/YwAY2sBVhiygP1mi9ed0DbGADWw22e0R58FmxSarABjaw
FWGLKA+uFdu7fYENbGADWw22jPKgr9s0pQpsYANbEbaI8uD6taPfwQY2sIGtBltEebDaMQ4R
PNjABrYibBHlwerHPg6wgQ1sYKvBFlEeXCu2ftiKgg1sYCvCFlEe7L6+5m+8wAY2sIHtT9gi
yoPP0+C2omADG9iKsEWUB5/rHlZsYAMb2GqwPSLKg/0ae5h5ADawga0IW0R5sG/ns7ugCzaw
ga0IW0Z58Brn8I0NbGADWxG2jPJgtLO5oAs2sIGtCFtEebDHWmuCDWxgA1sNtojyYK/9NqUK
bGADWxW2iPLgM6XKe2xgAxvYirBllAf7WrO5xwY2sIGtCFtGebD3aUoV2MAGtipsEeVBf89z
iODBBjaw1WB7RpQH/XXBdgMb2MAGthpsGeXBNjAZbGADWx22iPKgPebjdEEXbGADWxG2iPKg
3eb99I0NbGADWxG2iPJgvtZaYAMb2MBWhC2iPHiP0butKNjABrYibBHlQbtfW9EH2MAGNrDV
YMsoD87VPA0ONrCBrQpbRnlwrvf6BhvYwAa2GmwR5cGeWlGwgQ1sZdi+I8qDfV60mXkANrCB
rQhbRnkw92O77gE2sIGtCFtEebDPdawX2MAGNrDVYIsoD+ZtjWlKFdjABrYibBnlwWPN9QU2
sIENbDXYIsqDPRwegA1sYKvDFlEeXKw9t/IAbGADWxG2jPLgZ0qVwwOwgQ1sRdgiyoPz69qJ
SqrABjawFWGLKA/GWH16QRdsYANbDbZXRHlw3q4Vm7miYAMb2IqwRZQHa/VHm2ADG9jAVoMt
ojy4fu3dTakCG9jAVoQtojxYs632BhvYwAa2GmwR5cG1FX3aioINbGCrwpZRHvy8oGvFBjaw
ga0IW0Z5cK6XF3TBBjawVWHLKA9+ni2yYgMb2MBWhC2iPNjP8Rxe9wAb2MBWhC2iPLh+rXdb
UbCBDWw12N4R5cFa/d4kVWADG9iKsKWUB9/tN15gAxvYwPYnbBHlwZ77bpgL2MAGtipsEeXB
BzZJFdjABrYibBHlwf4er+EFXbCBDWxF2DLKg/d8TNc9wAY2sBVhyygPHuc4XdAFG9jAVoQt
ozxY+9ieBgcb2MBWhC2iPOh7rmHFBjawga0IW0R50NscDg/ABjawFWE7IsqDPq8Vm/F7YAMb
2IqwRZQHe5sEDzawga0OW0R50M85hwgebGADWxG2jPKgzXM6FQUb2MBWhC2jPGhzzg42sIEN
bDXYMsqDYx7T4QHYwAa2ImwZ5cHazQVdsIENbFXYMsqDY3bf2MAGNrBVYYsoD3abwzc2sIEN
bFXYIsqDzzc21z3ABjaw1WBrEeXB5xtbAxvYwAa2GmwR5cE62+vYYAMb2MBWgy2iPFijjWYr
Cjawga0IW0R5cK3Y7ofDA7CBDWxF2CLKg2vFdjTDXMAGNrAVYcsoD/q6LzMPwAY2sBVhiygP
rq3o85hgAxvYwFaDLaI8uLairRmYDDawga0IW0R5sHr7OiRVYAMb2IqwZZQHe69tKwo2sIGt
BNvj3z/C/xm2/px9ODwAG9jAVoQtojzorws21z3ABjawFWGLKA/2sBUFG9jAVoctozyYbTWH
B2ADG9iKsGWUB6s/22+8wAY2sIHtT9gyyoNzvZeZB2ADG9iKsGWUB7PfmggebGD7j2H7BwAA
///s3bvN5TYQgNGWdPWiWI746r8Ey5s4sIMJPcDBFvAniwPyit9MXthylAfzvap5bGADG9iC
sOUoD0Yd1VUUbGADWxC2FOXBn6toAxvYwAa2EGy/FOXBB9tW7TwAG9jAFoQtRXnwHH28YAMb
2MAWhC1FefCcYAMb2MAWhy1FeXDNNmypAhvYwBaFLUV58Gy9vb6Kgg1sYAvClqI86H2+o4MN
bGADWwy2FOXBuOacxhaBDWxgC8KWojwY5xxgAxvYwBaFLUV5UEp/XhN0wQY2sAVhS1EelOeD
zYkNbGADWwy2PUV5UN5eX+v3wAY2sAVhS1Ee9HOW4bkH2MAGtiBsKcqD3uY7RPBgAxvYgrCl
KA/68I4NbGADWxy2FOVBOfpdbakCG9jAFoQtRXlQzl4scwEb2MAWhS1FeVB2JzawgQ1scdhy
lAd1rnmCDWxgA1sMthTlQX9nHbZUgQ1sYAvClqI86M8Hm0GTYAMb2GKwHSnKgzbmOSRVYAMb
2IKwpSgP7qf/rN8DG9jAFoUtRXlQ9n5VD3TBBjawBWFLUR7Me13Tcw+wgQ1sQdhSlAfzt47p
qyjYwAa2IGwpyoPvxHY6sYENbGCLwpaiPPhObLsTG9jABrYobCnKg9lWWZ57gA1sYAvClqI8
eEqfr3lsYAMb2IKwpSgPrtb647kH2MAGthhsZ4ryYO2rLg90wQY2sAVhS1EerHO9q4ANbGAD
Wwy2FOXBqGubF9jABjawxWBLUR6MuX7zARvYwAa2GGwpyoPRnNjABjawxWFLUR6Uq5e6wAY2
sIEtBluK8qDcvbwb2MAGNrDFYEtRHvQyn+E3NrCBDWxB2FKUB3OsZ+1gAxvYwBaDLUV5sOpo
dh6ADWxgC8J25SgPnlGG9XtgAxvYgrDlKA/67FMEDzawgS0IW5LyYC7v2MAGNrBFYUtRHsxu
HhvYwAa2OGwpyoPvKjqnsUVgAxvYgrClKA8+2AbYwAY2sEVhS1EejG328W+8wAY2sIHtP2FL
UR60dx5dKwo2sIEtCFuK8uDpY3vBBjawgS0IW4ryoG5jb5IqsIENbDHY7hTlwb23VT33ABvY
wBaELUV5cP/ABjawgS0OW4ry4D4+2FxFwQY2sAVhS1EelK1fVSsKNrCBLQhbivLgbv2oBk2C
DWxgC8KWojy4+webeWxgAxvYgrClKA/ut+/VwmSwgQ1sQdhSlAerzk1SBTawgS0KW4ryYNWx
xgAb2MAGthhsKcqDda22fDwAG9jAFoOtpCgP1lhzObGBDWxgC8KWojxY79yHCB5sYANbELYU
5cE61rt8FQUb2MAWhC1FeTDXetYBNrCBDWwx2FKUBx9rfb1gAxvYwBaDLUV5sO7VlvIAbGAD
WxC2FOXBs8avGVsENrCBLQhbivLgz6BJY4vABjawBWFLUR48Zx+v39jABjawBWFLUR48ta/X
XlGwgQ1sMdieFOXB8/QJNrCBDWxR2FKUB22fW/dVFGxgA1sQthTlQevzGBvYwAY2sMVgS1Ee
9GPe4wIb2MAGthhsKcqDe/Wz+ioKNrCBLQhbnvLAPDawgQ1sQdhSlAdrX++6wQY2sIEtBluK
8mDNv/+BDWxgA1sMthTlwaqme4ANbGCLw5aiPGjX/HWb4MEGNrDFYKspyoM/sCkPwAY2sAVh
S1Ee1D5KcxUFG9jAFoQtR3lwuoqCDWxgi8OWojyobdxNKwo2sIEtCFuK8qCM/r4n2MAGNrDF
YEtRHtQyzuaBLtjABrYgbCnKgz9XUR8PwAY2sAVhy1EePKOY7gE2sIEtCluO8qCMvS+wgQ1s
YIvBlqI8+GA7h/V7YAMb2EKwnf/8R/ifw3aNA2xgAxvYYrClKA9amXsfYAMb2MAWgy1FeTCf
5y5gAxvYwBaELUV58MF2FM89wAY2sAVhS1EezPq0x29sYAMb2IKwpSgPVp3bcBUFG9jAFoQt
RXkwS1lFUgU2sIEtCFuK8mDepRdXUbCBDWxB2FKUB9+JbRZJFdjABrYgbCnKg++vGVsENrCB
LQrbL0d5cPSt2XkANrCBLQhbivKgPuNqBWxgAxvYYrClKA9qBdv/Gba/AAAA///s3UuO5DYQ
RdEt6S9yOSIjYv9LcHZOPKhsOADbyBfoWwuo4YGSuo8CNmBTg63E8mBufnEfG7ABG7BlYSux
PIjHd9+ADdiADdhysNVYHlgszkWTwAZswJaErcTywCxW54wN2IAN2JKwlVgexPTp3O4BbMAG
bEnYSiwPLGJzPpgMbMAGbEnYaiwPRj8agS6wARuw5WDbSiwPXrCdjWuLgA3YgC0JW4nlQUze
igIbsAFbHrYSy4M45jp4YgM2YAO2JGwllgexju0BNmADNmBLwlZieTAOX+YANmADNmDLwVZj
eXDbOn/iBWzABmzA9hG2EsuDF2wbsAEbsAFbFrYSy4P3B5OBDdiADdiSsJVYHvjTrPGVKmAD
NmBLwlZjefA0b4zggQ3YgC0H215jedDaeTOpAjZgA7YkbCWWB95bbyuwARuwAVsOthLLg9cT
23HTsQEbsAFbErYSy4PHzCbfPAA2YAO2JGwllgdPszl3YAM2YAO2HGw1lge//ujYgA3YgC0J
W4nlgVuP3oAN2IAN2HKw1VgezN76AmzABmzAloOtxvJg9J2rwYEN2IAtC1uN5cHoWyP3ADZg
A7YcbEeJ5UF7ZnDRJLABG7BlYSuxPGj7nA8vD4AN2IAtCVuJ5YE1Dz+ADdiADdhysJVYHtw2
n4flAbABG7AlYSuxPLhjDmADNmADtixsJZYHtrk5HRuwARuwJWErsTyY4cN+4gVswAZswPYR
thLLg+kv2Mg9gA3YgC0JW4nlwd1nfzZgAzZgA7YcbCWWB9EtjEkVsAEbsOVgO0ssD2KJHrwV
BTZgA7YkbCWWB2/YCHSBDdiALQlbieVBPGHBCB7YgA3YkrCVWB7EHTM6sAEbsAFbDrYSy4Nm
tjwBbMAGbMCWg63E8qC5rYPlAbABG7AlYSuxPPAtdueMDdiADdiSsJVYHniPK3hiAzZgA7Yk
bCWWB3a5O98VBTZgA7YkbCWWB/c1787LA2ADNmDLwXbVWB50c+OMDdiADdiSsJVYHvgZh7MV
BTZgA7YkbCWWBzZj9RvYgA3YgC0HW4nlga0+uWgS2IAN2LKwlVgeWMTmfH4P2IAN2JKwfXF5
8OElQYTF/H8g+kzMf24JbMDGH8DGF7v+37BhsAEbsKHNxher+Y9sTJ42YAM21Nn4YpP+YQYd
to0VNmADNrTZ+GLx/U+3J8AGbMCGJBv3F3vqn2z0hacN2IANfTa+WCt/PNtwjkRhAzbU2fhi
C/zxbGPlaQM2YEOdjS+Wth9+pKyvHykbbMAGbGiz8cWO9TdnG7ABG7AhzoZaJTr+/iQSbMAG
bGiyoVaJjnhgAzZgQ5sNqUq0b7aPHTZgAza02ZCqRPvxYuOADdiADW02pCrRZ7E26DZgAza0
2WhSlegT5vOGDdiADW02pCrRvvMjBTZgQ58NqUq0n3aMEzZgAza02ZCqRN+bFIcN2IANbTa0
KtGwNrimBzZgQ5wNqUr0fbZBtwEbsCHOhlQlOhc/DTZgAzbE2ZCqROftzRpswAZsaLMhVYk+
l43JfRuwARvibEhVovcx786bFNiADW02ulQleu0jOvdtwAZsiLMhVYneJ08bsAEb+mxIVaLX
+nra4GwDNmBDnA2tStTjDOJy2IANcTakKtFoMbndCzZgQ50NqUo0LNbgq2ywARvibEhVonHE
E9y3ARuwIc6GViW6+2WcbcAGbIizIVWJzsNvu2ADNmBDmw2pSrRvtrGAhQ3Y0GbjXKQq0bA4
AjZgAzbE2ZCqRN9scJcobMCGOBtSlWh43MHZBmzAhjgbUpXoPDkShQ3Y0GdDqhKdjWt6YAM2
9NmQqkT7xQcPYAM29NmQqkSfbnPyJgU2YEOcDalK9NrnwjU9sAEb6mxIVaLRY8aADdiADW02
pCrROGMER6KwARvabKxSleh7k8KRKGzAhjgbUpXou9tgOA8bsCHOhlQlOi9vsAEbsKHOhlQl
+ix8Oho2YEOfDalK1A435+Zy2IANcTakKtEx/TDuEoUN2BBnQ6oSve/ZHtiADdgQZ0OrEm1z
7byAhQ3YEGdDqhK9fY4HNmADNsTZkKpE721e3WADNmBDmo1NqhJ9f8yRSwFhAzbE2ZCqRGOG
BU8bsAEb4mxoVaK/bvfqsAEbsKHNhlQlOsJP45oe2IANcTakKtF4/Vu+OA8bsKHOhlQlGsaR
KGzAhj4b/6oS/QsAAP//7N2JDR0hDADRlvZeKAds038J+dkeIk2kaeKJYzD/YLXRHdMjG7JB
ZwNViY4z+1yyIRuywWYDVYl+v7I5b0M2ZAPOBqoS/Y5EvYCVDdlgs3GiKtE56gw3KbIhG3A2
UJXouHOED+dlQzbgbKAq0dnqiJIN2ZANNhuoSnS8OcNf2WRDNuBs0CrRZz2yIRuywWaDVYnW
auZesiEbdDZQleic3qTIhmzw2WBVopc3KbIhG3w2UJXoaB6JyoZs8NmgVaLPcgSxbMgGm40L
VYmuXPvyVzbZkA04G6hK9Jvu5SZFNmQDzgarEp11+pmjbMgGnQ1UJfqN6fEFrGzIBpwNVCU6
ZmZ4JCobsgFnA1WJzrO2cASxbMgGnA1WJXrVHlM2ZEM22GygKtG1VizZkA3ZgLPBqkTPHI4g
lg3ZoLOBqkRHyzAulw3ZgLNxsyrRvw/nnVwuG7IBZwNVib53vN1NimzIBpwNVCXaRqyRsiEb
ssFmA1WJti4bsiEbfDZQlejd5mxewMqGbMDZQFWi9/tjw0pUNmQDzgaqEr27qw3ZkA0+G6hK
9B3Rh92GbMgGnA1UJfrdpJRsyIZssNlAVaLtjhyebciGbLDZeFCV6B0zmxewsiEbcDZQleid
PzbcpMiGbMDZQFWid8mGbMgGnw1UJfr2aN6kyIZs0NlAVaKtxRohG7IhG2w2WJVozWq+gJUN
2YCzwapEl2zIhmzw2UBVot8FrEeisiEbcDZQlejbog3/gJUN2YCzwapEM/fhJkU2ZIPNxouq
RFvkJhuyIRt0NliVaHPehmzIBp8NVCX6zujjlA3ZkA02G6hKtM3fJsWbFNmQDTgbqEr0rRjD
H+dlQzbgbKAq0XZEjCYbsiEbbDZQlWhveU9/ZZMN2YCzwapEp2N6ZEM2+GygKtFnm9U32ZAN
2WCzgapEnzu27gWsbMgGm42GqkTfiDEu2ZAN2WCzgapE/75JmW5SZEM24GywKtGwEpUN2eCz
wapE06dssiEbfDZQlei8agv/gJUN2YCzgapE5127bMiGbNDZQFWi480ZTveSDdmAs4GqRGfW
lbIhG7IBZwNVic5eZ/hwXjZkA84GqhJdubbyJkU2ZIPNRkdVojGqp0MBZUM24GygKtHY60nj
ctmQDTgbqEo0Zo30AlY2ZAPOBqoSHZEZDgWUDdmAs4GqROOsN2VDNmQDzgarEq268pAN2ZAN
NhuoSnT2Ouw2ZEM26GygKtGV61yuNmRDNuBssCrR97facASxbMgGnA1UJTr3XOE/KbIhG2g2
no1ViT71pv+kyIZswNlAVaKzuUmRDdngs8GrRH2TIhuyAWcDVYnG4ZsU2ZANPhuoSrS/ec1H
NmRDNthsoCrR/siGbMgGnw1UJdq7P87Lhmzw2UBVor9NimzIhmzg2UBVoh8bblJkQzbgbKAq
0T7ymV02ZEM20GzsqEq0R77TbkM2ZAPOBqoS7fO32pAN2ZANOBuoSrSnqw3ZkA0+G6hK9LuA
9QWsbMgGnA1WJTo9EpUN2eCzwapE+48NVxuyIRtwNlCVaB4V6WeOsiEbcDZQlWi06ukmRTZk
A84GqhL9rTayNtmQDdlgs4GqRFeuY+2yIRuygWbjQFWimWsvn7LJhmzA2UBVotlqldO9ZEM2
4GygKtF8qsrvlWRDNuBsoCrRXOsob1JkQzbgbKAq0QzPNmRDNvhsoCrR2lxtyIZs8NlgVaJz
beV0L9mQDTgbrEq0W4nKhmzw2WBVoqeVqGzIBp8NVCWa3W5DNmQDz8aJqkRXrK18ASsbsgFn
A1WJrlznOmVDNmSDzQaqEo2qmSkbsiEbbDZQlWgd66wpG7IhG2w2WJXo7ZsU2ZANPhusSnRf
R/nhgWzIBpwNViU61la3bMiGbLDZQFWidXq2IRuywWcDVYmutcZykyIbsgFnA1WJfj/O+0+K
bMgGm40LVYmOygrnbciGbMDZQFWizxt790hUNmQDzgarEo0a6ZGobMgGnA1UJbqiVpVsyIZs
sNlgVaJbRcqGbMgGnA1UJZq7X0fLhmzw2UBVouPIPl1tyIZswNlAVaJzzxXOEv1/2PgDAAD/
/+zdW27cRhCF4a14AzY4M7w0l9NdXRUEMCxD0f4RmgKiKNZDDWBgTsf/s2zIhjQfePkPCRu/
KRtSlei62mXnoYCwARvibEhVota9dYMN2IANaTYWrUq09268JwU2YEOcDa1K1Oy2c20DNmBD
nA2tSrR75SQFNmBDnQ2pSrRNPYwFLGzAhjgbUpXo+Z4Uug3YgA1xNqQqUQteeAAbsKHPhlQl
erLB0QZswIY4G1qV6OIX45IobMCGOBtSlej5dC+6DdiADXE2pCrR2no34nLYgA1tNlapSrS5
z/0CG7ABG9psSFWibfOLcScFNmBDnA2pSrRdfWI4Dxuwoc6GVCW67VYqJymwARvibEhVoktt
VrgBCxuwIc6GVCV6HG3s9QobsAEb2mxIVaJbt1q5AQsbsCHOhlQlukTzfYIN2IANbTakKtFl
b1Z4KxtswIY4G1KVaKl9qkzZYAM2tNnYpCrRsppXjjZgAzbE2ZCqRMtkrTJlgw3YEGdDqhI1
54UHsAEb+mxIVaJxuOFsUmADNsTZkKpE+3awcYMN2IANbTakKtHmvnQqUdiADXE2pCrRtvJQ
QNiADX02pCrR3XtpsAEbsCHOhlQlerJBtwEbsCHOhlQlultfW4UN2IANaTaKVCVaL31vxOWw
ARvibEhVonXutQVswAZsaLMhVYmeRxvkXrABG+JsSFWiu/eNS6KwARvqbGhVoh5XL7ABG7Ch
zYZUJeolVufaBmzAhjgbUpWo77ABG7Chz4ZUJXqcpFw4SYEN2FBnQ6oSDfNgOA8bsKHOhlQl
ej5vg00KbMCGNhu7VCXqLdbgZY6wARvibEhVor7F4sTlsAEb4mxIVaLH0cbG0QZswIY6G1KV
qM8xc20DNmBDnQ2pSjR6XIOHAsIGbIizoVWJ7rEG74CFDdgQZ0OrEl1joduADdhQZ0OqEnXj
kihswIY+G1KVqN+4JAobsKHPhlQl6h4leL0SbMCGNBvbJFWJxhR7LLABG7ChzYZWJVq5kwIb
sKHPhlYleomb88ID2IANcTa0KtEeG7kXbMCGOhtSlagvMdNtwAZsqLMhVYmGeecGLGzAhjob
epUow3nYgA1xNh5YiT49Hz+4z6+fqH/91D56xujk1v3to1//ePp2fOra188vz+9/I/752svx
5ecPflt+GUNv/4PXD+b7f8V7nN7+7PPrL+P0ZZu/v3z66+nrn/3Tfz6Rv9Cwt+/78vT9/V8A
NmD7X8P2wI71DtguB2wBbMAGbMCWg+2Bpe0dsF2BDdiADdjSsF0e2ALfAdvNu0/ABmzABmw5
2B5YK+dhK5O1ugEbsAEbsOVge2BPfSdsK7ABG7ABWw62Bxbfedisee0N2IAN2IAtB9sDm/Q7
YNt97zuwARuwAVsOtgdW83fAVg/YKrABG7ABWw62B3b9d8BWvHDEBmzABmxZ2IZYHmzBzQNg
AzZgy8M2xPJgc6t1ATZgAzZgy8E2xPLgPBUtwAZswAZsKdiuQywPbD1gI9AFNmADtiRsQywP
tn6cis7ABmzABmw52IZYHvTF3S/ABmzABmw52IZYHpywXYEN2IAN2HKwDbE86MXDORUFNmAD
tiRsQywPysWMp3sAG7ABWxa2IZYH5QpswAZswJaHbYjlwQkbHRuwARuwJWEbYnlgxmOLgA3Y
gC0P2xDLg82tMakCNmADtiRstzGWBz8eNMlji4AN2IAtCdsQywPb2IoCG7ABWx62IZYH56SK
U1FgAzZgS8I2xPLgfB4bsAEbsAFbErYhlgc+x+wGbMAGbMCWg22I5UEch2zBzQNgAzZgS8I2
xPLggK0F7zwANmADtiRsQywPIsLjZ7yADdiADdg+hG2I5UFZrFdORYEN2IAtCdsQy4OyW9QO
bMAGbMCWgm0eYnmwX/ut3YAN2IAN2HKwDbE8qEuvNgEbsAEbsOVgG2J50GfvvPMA2IAN2LKw
DbE8KLP1Su4BbMAGbEnYhlgelM288jw2YAM2YEvCNsTywMJb564osAEbsCVhG2J5YP2Aja0o
sAEbsCVhG2J5YM4RG7ABG7DlYRtieXCeiv6MF7ABG7AB24ewDbE8sOY7jwYHNmADtiRsyxDL
AysHbOQewAZswJaEbYjlQS8ezqQK2IAN2JKwDbE8iMKDJoEN2IAtD9sQy4P9xgge2IAN2PKw
DbE8qDMjeGADNmDLwzbE8iCa774BG7ABG7DlYBtieRDmnbdUARuwAVsWtiGWB+cRG2+CBzZg
A7YkbEMsD44jNnPuigIbsAFbErYhlgfReUsVsAEbsKVhW4dYHvgea3BXFNiAbWjY/gYAAP//
7N27kSM7DEDRlPTrXzjdJJB/CCvJWWPGgLX1UO8ogXGmTlECL/gvYWtRHuT3AzawgQ1sNdha
lAex5CusLQIb2MBWhK1FefAdHlgNDjawga0IW4vyIK9Y4wU2sIENbDXYupQHWyxgAxvYwFaD
rUd5cMZibRHYwAa2KmwtyoMYueUDbGADG9hqsPUoDz4fF3TBBjawFWFrUR7EzD19FQUb2MBW
g21rUR5k5Jor2MAGNrDVYOtRHsy8hfIAbGADWxG2FuXB+8S2pUWTYAMb2Iqw9SgPrtjDV1Gw
gQ1sRdhalAfXEY9hKgo2sIGtCFuL8uA64zn8xgY2sIGtCFuL8iBW2z3ABjaw1WFrUR58W1G/
sYENbGArwtaiPIhwQRdsYANbHbYe5cGeq3tsYAMb2Iqw7T3KgxFXHGADG9jAVoOtR3lwxits
9wAb2MBWhK1HeXDFYoMu2MAGtipsPcqDM55xBxvYwAa2GmwtyoN85akVBRvYwFaFrUV5kMsb
th1sYAMb2GqwtSgPvvvYPOYCNrCBrQhbj/JgRMZPvMAGNrCB7VfYWpQH14zXNDwAG9jAVoSt
RXkwZ97D8ABsYANbDbajR3nw2aArggcb2MBWhK1HeTDzlS7ogg1sYCvC1qM8GO8zm31sYAMb
2IqwtSgProxlakXBBjawFWHrUR6c8Ygb2MAGNrDVYOtRHpxxn/axgQ1sYCvC1qM8OOI2XdAF
G9jAVoStR3mQOQ0PwAY2sFVha1Ee5IgZF9jABjaw1WBrUR5877F5zAVsYANbCbb97z/Cfxm2
8Yh12u4BNrCBrQhbi/IgDq9UgQ1sYKvD1qI8GEtsUysKNrCBrQhbi/Igh6ko2MAGtjpsPcqD
fa7T8ABsYANbEbYe5cExr+nNA7CBDWxF2HqUB9u0QRdsYANbGbYe5cE+D8MDsIENbFXYepQH
kbvn98AGNrBVYetRHrz/XB5gAxvYwFaC7d6iPPjCdoINbGADWw22FuVBnvEK1z3ABjawFWFr
UR7kPrfpMRewgQ1sRdh6lAfbvI+feIENbGAD26+w9SgPtvmc3jwAG9jAVoStR3mQnt8DG9jA
VoetR3lwzJgDbGADG9hqsPUoD7b5GPaxgQ1sYCvC1qM8WMccLuiCDWxgK8LWpTw4lAdgAxvY
irA9epQHy7jGBjawgQ1sNdh6lAfryGF4ADawga0IW4/yIPMtG9jABjaw1WDrUR7MfKRFk2AD
G9iKsPUoD644w/AAbGADWxG2HuXB7s0DsIENbHXYepQHI95nNrCBDWxgq8HWozz4rAZ33QNs
YANbEbYe5cEy1vEAG9jABrYabD3Kg3UMSRXYwAa2ImzPHuVB5pUX2MAGNrDVYOtRHsy8h+0e
YAMb2IqwtSgP5pW38GAy2MAGtiJsPcqDERE26IINbGArwtanPHBBF2xgA1sRth7lwS339Pwe
2MAGtiJsLcqDeOYzTEXBBjawFWHrUR7c88gFbGADG9hqsLUoD+KWD9s9wAY2sFVha1Ie5JWG
B2ADG9hqsL1alAeRhgdgAxvY6rD1KA8eeaQLumADG9iKsLUoD/JmeAA2sIGtDluL8iC2XOIn
XmADG9jA9itsPcqDz/DAVBRsYANbEbYW5UE8XNAFG9jAVoetRXmQRw772MAGNrBVYetRHpw5
PZgMNrCBrQpbi/LgDZsTG9jABrYybC3Kg/eBLYZXqsAGNrDVYFtalAfXEvfhxAY2sIGtCFuP
8uCKPZzYwAY2sBVh61EeDMMDsIENbHXYWpQHuc7bABvYwAa2Imw9yoNtvqaX4MEGNrAVYWtR
Hrxhuw+vVIENbGArwtajPIg8LJoEG9jAVoWtR3nw+Y3NiQ1sYANbEbYe5cEyjmHRJNjABrYi
bC3Kg1zHGL6Kgg1sYKvBtrYoD96wpfIAbGADWxW2HuXB56uo1eBgAxvYirD1KA8iF28egA1s
YKvC1qM82Obigi7YwAa2Kmw9yoN9rtO7omADG9iKsPUoDy4RPNjABrY6bD3Kg2Vsw4ntfwLb
HwAAAP//7N1BjuM4DEDRKyWxndjHsUTx/kfo6toMMFULArMZAg+5QvBgW/wU2MD232FrUh7M
ZdwDbGADWxW2HuXBPvf5ABvYwAa2Gmw9yoNj3pIqsIENbEXYPj3Kg8gtjXuADWxgK8LWozzY
5zGfYAMb2MBWg61HebDP1/iJF9jABjaw/Qpbj/Ig8kjjHmADG9iKsLUoD1bkxzc2sIENbFXY
WpQH54jH7VUUbGADWxG2FuXBOb9gS7CBDWxgq8HWojyI14plQBdsYANbEbYW5cGc6w4RPNjA
BrYibC3Kg3Ob83bnAdjABrYabGeL8uC8Z96u3wMb2MBWhK1FefB9eOBUFGxgA1sRthblwbnP
uG+wgQ1sYKvB1qI8WHe+06ko2MAGtiJsLcqD6xGvIYIHG9jAVoStRXlwnXGMD9jABjaw1WBr
UR7cM8KFyWADG9iqsPUoD95rLRE82MAGtiJsLcqD+HzBtoENbGADWw22FuVBXCuXfWxgAxvY
arBdPcqDa+atFQUb2MBWhK1HefCe63avKNjABrYibC3Kg7mvT7h+D2xgA1sRthblQax8Lts9
wAY2sBVha1EezOPric2ALtjABrYibC3Kg/XOY/3EC2xgAxvYfoWtRXlwHbEP5QHYwAa2Imwt
yoN7i3u4zAVsYANbEbYW5cH1iWM4FQUb2MBWhK1FeXBfMaekCmxgA1sJtuufP8L/GbZcf39g
AxvYwFaDrUV5cO2xDa0o2MAGtiJsLcqDjHxaDQ42sIGtCluP8mBbsawGBxvYwFaErUV5kJl3
uqUKbGADWxG2FuXBlXEOa4vABjawFWFrUR7cEWuaYwMb2MBWhK1FeTC29ZheRcEGNrAVYetR
HjzjNVzmAjawga0IW4vy4BrxHhfYwAY2sJVge7YoD64Vn2E1ONjABrYibC3Kg8ycCTawgQ1s
Rdh6lAeZkcY9wAY2sBVha1EerGe+llNRsIENbEXYWpQHMfO5zLGBDWxgK8LWojyI/HpicyoK
NrCBrQhbi/Ig3mstiybBBjawFWFrUR7Ea81lbRHYwAa2ImwtyoNzm3F7FQUb2MBWhK1FebCe
uTkVBRvYwFaE7dWiPDjfc91gAxvYwFaErUV5cK54Dt/YwAY2sBVha1EeXFcc4wQb2MAGthps
LcqD7wHdD9jABjaw1WDrUR78HdD1xAY2sIGtCFuP8uBauQ6wgQ1sYKvB1qM8mPnQioINbGCr
wtaiPPge0PUqCjawga0IW4/y4J55/8QLbGADG9h+ha1FeXBmPIeb4MEGNrDVYNt6lAeH8gBs
YANbHbYW5UHc+XAqCjawga0KW4vyIK+c6YkNbGADWxG2FuVBHjnSqSjYwAa2ImwtyoO81yOc
ioINbGArwtaiPBj32ibYwAY2sBVha1EejPEFW4INbGADWw22FuVBXpERYAMb2MBWg61FeTDm
2sOiSbCBDWxF2FqUB7nlnSJ4sIENbDXY9hblQY71NqALNrCBrQpbi/Igr4gYYAMb2MBWg61J
eRAj3CsKNrCBrQhbi/JgPtYRG9jABjaw1WBrUR7Mbb3DNzawgQ1sRdhalAf5nmNqRcEGNrAV
YWtRHnzBtqbtHmADG9iKsPUoD/b5ni+wgQ1sYKvB1qI8yMxhHxvYwAa2Kmw9yoMz7nATPNjA
BrYabEeP8mCbjzHBBjawga0GW5fyYCkPwAY2sFVha1EejHO9prVFYAMb2IqwtSgPMnIl2MAG
NrAVYWtRHnwvmvSNDWxgA1sRth7lwTHv6VQUbGADWxG2LuVBKA/ABjawVWHrUR584uWWKrCB
DWxV2HqUB8f8TGuLwAY2sBVh61Ee7HMbrt8DG9jAVoPt3aM8iNzSExvYwAa2Imw9yoN9voY5
NrCBDWxF2FqUB7mNNdx5ADawga0IW4/yYJ+7b2xgAxvYqrD1KA+2kcMcG9jABrYibD3Kg23M
oTwAG9jAVoStR3mwz6fDA7CBDWxV2HqUBzMfyzc2sIENbEXYepQHW97pVRRsYANbEbYW5cH1
jNcwoAs2sIGtBtunRXkQn5ULbGADG9iKsLUoD85z5m3RJNjABrYibC3Kg/Mz179h+wMAAP//
7N3dDds4EADhlixZfyyH5HL7L+EUvSRAHJwe7uARMq7B+EBSs6SwCZuwCdufYHvE5MGRMbdJ
2IRN2ITtHmyPmDyIkfM4hE3YhE3Y7sH2iMmD43ArKmzCJmz3YXvE5EF5nVvRWdiETdiE7R5s
j5g8KFssbRU2YRM2YbsH2yMmD9oyXr0Jm7AJm7Ddg+0RkwfjncvwjE3YhE3Y7sF2PGLyIEeu
uQibsAmbsN2D7RGTB6PnnnZswiZswnYTtkdMHpQeuzfoCpuwCdtd2B4xeVDihM2PB8ImbMJ2
E7ZHTB60V2R38kDYhE3YbsL2iMmD7COHV4MLm7AJ203YHjF5ULeo3Y8HwiZswnYTtkdMHrR9
zN0Vm7AJm7DdhO0Rkwd1j+aKTdiETdjuwvaIyYM6RWm/4yVswiZswvYJtvKIyYNrCH4TNmET
NmG7B9sjJg+yj+GsqLAJm7Ddhe2LkwcfLpSsPWv8PxB9Juc/t0Q2ZOMvYOOLXf8HNiKmmrIh
G7LBZuOL1fwHNube6yEbsiEbbDa+2KT/4QG2JhuyIRtsNr5YfH983mz6+byZbMiGbDDZ+GJP
/eFj9RLvtsiGbMgGm40v1sof2Fh/fehBNmRDNphsfLEF/rBJWXvUKhuyIRtgNuZf/ggINo6e
Px8ClQ3ZkA0mG1/sWH9nY++9Vs82ZEM24GywKtHpdGOXDdmQDTYbqEr0etTbD7CyIRtwNliV
aI+XcblsyAadDVQluh/9qK42ZEM24GygKtE9e6ubbMiGbLDZQFWiR7hJkQ3Z4LOBqkSP9EhU
NmSDzwarEm3namPIhmzIBpqNiVWJjpjaSzZkQzbYbKAq0bpG7bIhG7IBZwNVidaM0a1EZUM2
4GywKtGIvXm7l2zIBpwNVCV6vQI4y4ZsyAabDVQlWnpszfs2ZEM24GygKtH6/vVpTtmQDdlg
soGqRM/Vxu5qQzZkg84GqhItzU2KbMgGnw1UJVpnNymyIRt4NmZUJVqmmNtbNmRDNthsoCrR
ssfazL1kQzbgbKAq0YsN79uQDdmAs8GqRH8ciRbZkA3ZYLOBqkRLlQ3ZkA0+G6xKNONoPq8k
G7IBZwNViZYtFs82ZEM26GywKtFdNmRDNvhsoCrRjFzSxxxlQzbgbKAq0YsNcy/ZkA02G29U
JZojt3STIhuyAWcDVYlebKyyIRuywWYDVYnm9ZMN2ZANNhuoSvRSwwlY2ZANOBuoSvREIzJk
QzZkg80GqhI92ejpzeWyIRtwNlCV6LnWWO02ZEM26GygKtEfJxuebciGbNDZYFWiI3e7DdmQ
DTobqEp0H71Vuw3ZkA02GwuqEj3evddDNmRDNthsoCrR8o63VxDLhmzQ2UBVomWJpblJkQ3Z
gLOBqkSPrY9qtyEbsgFnA1WJ7r3X6iZFNmQDzgaqEt3jZMPcSzZkA84GqhItr5jbLBuyIRts
NlCV6PWYo2zIhmzA2UBVosfSo/pOimzIBpwNVCVaZrsN2ZANPBsrqhKtU5TmKJtsyAacDVQl
Wmv07pcU2ZANOBuoSvRabXi7l2zIBpwNVCVal6jNK4hlQzbgbKAq0TJib8blsiEbcDZQlWh9
xeEmRTZkg84GqxI9Ym27bMiGbLDZYFWiNbbmNT2yIRtwNlCV6HWXqKsN2ZANOBuoSjQzm++k
yIZswNnYUJVo1gzZkA3ZoLOBqkTPtUZklw3ZkA02G6hKNLcTDidgZUM24GygKtE8smeVDdmQ
DTYbqEo0Rk7DD7CyIRtwNlCVaBZfnJcN2eCzgapEo+Vr+AasbMgGnA1UJZr7udrwSFQ2ZAPO
BqoSHXHC4RXEsiEbcDZQlWjP0cIJWNmQDTYbO6oS7a+xhlcQy4ZswNlAVaIROQ1H2WRDNuBs
oCrRludqw7MN2ZANOBuoSnS8ch5WorIhG3A2UJVotrGNVTZkQzbYbLAq0TZ22ZAN2aCzgapE
s48x/AArG7IBZ4NVifZ8Dd9JkQ3ZgLOBqkTP1UaOIRuyIRtsNlCVaI48vIJYNmQDzsaBqkRP
Nkp634ZsyAacDVQlmuHZhmzIBp8NVCV6rTYcnJcN2YCzgapEr3dSrERlQzbgbLAq0bltbZIN
2ZANNhusSnRutVmJyoZswNlgVaJbH90riGVDNuBssCrRrWf3VTbZkA04G6xKtI51eLuXbMgG
nA1WJfpjcH6RDdmQDTQbhVWJLn3r3u4lG//Kxj8AAAD//+zdybHrIBQA0ZQ02BIKB+6Qfwhf
fkn8XnR57+UpuGpANv4vG6xKdF/HdLYhG7IBZ4NViV6RYe4lG7IBZ4NViX7jCbsN2ZANOBus
SjQqvIJYNmSDzgarEp31KUeisiEbcDZYleiTlY5EZUM24GzQKtEIr+mRDdmAs8GqRFc9PuYo
G7JBZ4NVid65R8mGbMgGmY19Y1WiUcsvKbIhG3Q2WJVod7QjUdmQDTgbrEr07OmDB7IhG3Q2
WJXo0U9fsiEbssFmg1WJbi8bxuWyIRtwNlCVaM7efHFeNmSDzgarEv0425AN2eCzgapE86n2
di/ZkA06G6xK9HhXG45EZUM24GygKtHKHu0JWNmQDTYbO6oSjaOudCQqG7IBZwNViVa/qw1n
G7IhG3A2UJVo7O9qQzZkQzbgbKAq0Rx+SZEN2eCzwapEq79uUmRDNuhsoCrRPzYcicqGbMDZ
YFWi1aO9FFA2ZAPOBqoS7dnRSzZkQzbYbLAq0U8cK2VDNmSDzQaqEn3ZOFfJhmzIBpqNA1WJ
9p2f3GVDNmSDzQaqEn3Z+KZnUmRDNuBsoCrRv3dS/JIiG7IBZwNVib5sTNmQDdmgs8GqREfe
nkmRDdmgs8GqRLOPdiQqG7IBZ4NVif5eZXtkQzZkg80GqxL9zTZkQzZkA84GqxIdObzdSzZk
g84GqxKNercpsiEbsoFm42RVorO2NC6XDdmAs8GqRLP33mRDNmSDzQarEv19gDUulw3ZgLPB
qkSzT9mQDdmgs8GqRLtnT9mQDdlgs8GqRK/cwmt6ZEM24GywKtEfGyEbsiEbbDZYleidu6sN
2ZANOhusSjQqy9WGbMgGnA1aJVqyIRuyAWfjw6pEb0eisiEbfDZQlWg9Yw67DdmQDTgbqEq0
5sjhCVjZkA04G6hK9GWjxiUbsiEbbDZQlWit5xgenJcN2YCzwapER15eQSwbskFng1WJ/tg4
ZUM2ZIPNBqoSrWeM4X0bsiEbcDZQlejLxhquNmRDNuBsoCrRmqPHLRuyIRtoNr60SvTrbEM2
ZIPOBqoSfdlwJCobsoFng1WJPuMZPuYoG7IBZ4NViT4jht2GbMgGnA1UJfpuUj7pUTbZkA04
G6xKtH4/2ZAN2WCzgapE6+nL55VkQzbobLAq0ei7HYnKhmzA2WBVond/y02KbMgGnA1UJdrp
bEM2ZAPPxoWqRGs625AN2eCzgapEaznbkA3Z4LPBqkRHf6tlQzZkg80GqxIdfcmGbMgGnQ1U
JfrrNmRDNmSDzgarEv095ugVxLIhG3A2UJVonyuW1/TIhmzA2UBVoi8btR7ZkA3ZYLOBqkT7
WMvVhmzIBp0NViX626QM2ZAN2UCzcaMq0b/Vho85yoZswNlAVaLjjJzONmRDNuBsoCrRcUfN
kA3ZkA02G6hK9H5iTC8FlA3ZgLOBqkTvijm/siEbssFmA1WJ3uNdbXhwXjZkA84GqhK9I57p
80qyIRtwNlCV6JjRs2RDNmSDzQaqEr1vNymyIRt8NlCV6D3fTYpfUmRDNthsDFQluq7aw25D
NmQDzgaqEp0jV7jakA3ZgLOBqkTXXUekbMiGbLDZQFWic2aEH2BlQzbgbKAq0RmZYSUqG7IB
ZwNVia49O7xvQzZkA84GqhJdZ20xZUM2ZIPNBqoSnWfO5YMHsiEbcDZQleh8HInKhmzw2UBV
ovPKGb4BKxuywWbjQVWic8uxrERlQzbgbLAq0c+72vAom2zIBpwNViXa9U1nG7IhG3A2UJXo
GnVEyYZsyAabDVYleubjB1jZkA06G6hK9DnzXB/ZkA3ZYLOBqkQ7utoTsLIhG3A2UJVoHHWl
qw3ZkA04G6hK9F1srHQkKhuyAWcDVYmuo7bwDVjZkA00G8eGqkT726s9OC8bsgFnA1WJ/t23
4WpDNmQDzgaqEp2ZFZdsyIZssNlgVaKbt3vJhmzw2UBVorX3Ud7uJRuyAWcDVYnW0Wct2ZAN
2WCzgapEV9QnPTgvG7IBZwNVic6VGVaisiEbcDZQlWivGnXLhmzIBpsNVCXa79+2I1HZkA02
GzurEk1PwMqGbPDZQFWi14zzcZMiG7IBZ+O/V6L/AAAA///s3dER4zYMANGWZMkSyXJIAOy/
hOj8c0kHO5NtwJ9vaGhJ/IeNjO8wLpcN2YCzgapEn2vtv48iy4ZsyAaTDVQl+rT41zOFsiEb
ssFkA1WJPj3O4VU22ZANOBuoSvSZLxuORGVDNuBsoCrR51g1DtmQDdlgs4GqRJ9z7eHqaNmQ
DTgbqEq0jRjTLymyIRtsNk5UJdqeaNM/KbIhG3A2WJXo8EuKbMgGnw1UJXr/uQLrDljZkA04
G6xK9ONIVDZkg88GqhJtzdmGbMgGnw1UJdpG9OlpQzZkA84GqhL98yVlONuQDdmAs4GqRNsR
9/DlctmQDTgbqEq0XfEMX/eSDdmAs4GqRPsRa9ptyIZssNm4UJXojw1vwMqGbMDZYFWiFd/h
y+WyIRtwNlCVaPvEPUI2ZEM22GygKtHfnhSfIJYN2YCzgapEd9tLNmRDNuhsoCrRfey+3QEr
G7IBZwNViT4R1+iyIRuywWYDVYk+dxzjkg3ZkA02G6xK9PZOimzIBp8NVCV6l8/0yIZs4Nn4
oirR32mjZEM2ZIPNBqoS/V1lkw3ZkA04G6hK9PclxW5DNmQDzgaqEq1nf8uL87IhG3A2UJVo
fV82vJMiG7IBZwNVib6njbucbciGbMDZQFWiPzb8kyIbsgFnA1WJVuy23QErG7IBZwNVieZT
VbIhG7IBZwNViWZ72fBOimzIBpuNG1WJ5v2y4Xol2ZANOBuoSjTPinKZo2zIBpwNVCWa30pP
G7IhG3Q2UJXo70+KI1HZkA04G6hKdM26wovzsiEbcDZQlWhe758UZxuyIRtwNlCV6Bp1hnG5
bMgGnA1WJXrtq9w4LxuyAWcDVYnGVU/esiEbssFmA1WJ7qjtVTbZkA04Gw+rEj0dicqGbPDZ
QFWi+44WbmWTDdmAs4GqRF82ZjTZkA3ZYLOBqkT3yJUuc5QN2YCzgapEXzYip2zIhmyw2UBV
ovsb1zIulw3ZgLOBqkR3z56PbMiGbLDZQFWiLxvN3Es2ZIPOBqoS3SMzjctlQzbgbMAq0Z3b
SlQ2ZIPNRkNVojFr+CVFNmSDzgaqEo0lG7IhG3w2UJVo9OrpxnnZkA04G6hKNMZ72pAN2ZAN
OBuoSjSe97ThnRTZkA04G6hKNNrLhndSZEM24GygKtFYNe02ZEM26GygKtF15g5nG7IhG3A2
UJXoavWJkA3ZkA02G6hKtHL37cZ52ZANNhsdVYlWyYZsyAafDVYlepU3YGVDNvBsoCrR3fJ0
B6xsyAadDVQl+rJxpQsPZEM24GygKtE965OeNmRDNuBsoCrRl43T9UqyIRt0NlCV6I59VMmG
bMgGmw1UJbrvWK5Xkg3ZoLOBqkT3E2FcLhuyQWcDVYn+niD2dS/ZkA02G4NVibZWzdxLNmQD
zgaqEq3ez+ZpQzZkA84GqhJ9f3VM76TIhmzA2WBVoseM6TJH2ZANOBuoSrRay7+vm8qGbMgG
kw1UJVqtH81uQzZkA84GqhJ9f7XNj2zIhmyw2UBVovW0aI5EZUM24GygKtFqbTdHorIhG3A2
UJVonhVenJcN2WCzcR2oSjTXPspKVDZkA84GqhLNIRuyIRt8NlCV6N47t3tSZEM24GywKtFr
7eUyR9mQDTgbqEp0j9yZsiEbssFmA1WJvqeNXG6clw3ZgLOBqkR/pw1nG7IhG3A2UJXo3dfq
zjZkQzbgbKAq0Xuu6J42ZEM24GygKtF2xj1kQzZkg83GB1WJtm88o2RDNmSDzQaqEr3bWt23
RGVDNuBsoCrRezgSlQ3Z4LOBqkTvvWocsiEbssFmA1WJ9shjOtuQDdmAs4GqRPs3cjrbkA3Z
gLOBqkQz9qd8glg2ZAPOBqoSrc++ytOGbMgGnA1UJfqeNo7yLVHZkA04G6hK9I6V3YvzsiEb
bDZOViW6wh2wsiEbeDZQlehadaXdhmzIBpwNVCUavXr6TI9syAacDVQlOs48l39SZEM24Gyg
KtGR2ZYfYGVDNuBsoCrRmZnhB1jZkA04G6hKdD65wo3zsiEbcDZQlWifXmWTDdngs8GqRFvt
ciQqG7IBZwNViUbWcuGBbMgGnI0LVYmuqm8625AN2YCzwapEUzZkQzb4bKAq0RXG5bIhG3w2
UJXofvbaxuX/Lzb+AQAA///snUtz5UQShf8K0TGLmYVFvR8EsHQM9nKWxCyupBI4wo8OP3j8
+8m6UjcNWO68crU6YQ5EuGlu6rpSKn11KuuUBGz8BbEhyiU6uBJH2L2ADWBDODZEuUQnOx0m
YAPYADaEY0OUS3RyhA1MUoANYEM4NkS5RI8LsAbYADaADdnYEOUSHYZygN0L2AA2pGNDlEt0
8pikABvAhnhsOFEu0eInV/AIYmAD2BCODVku0VI8ahvABrAhHRuiXKKDJmxgByywAWwIx4Yo
l+gQShzxMkdgA9gQjg1RLtFi8DJHYAPYkI8NUS7RcZpMycAGsAFsyMaGKJfoERtYgAU2gA3h
2BDlEi0KagPYADbkY0OUS3SK0zChtgFsABvCsSHKJTp4bJwHNoAN8djwolyivStqgNoANoAN
4dgQ5RKdpqlMMJcDG8CGcGyIcolOesqTBzaADWBDNjZEuUSLnVzBxnlgA9gQjg1RLtFpmMYJ
2AA2gA3h2BDlEqUpChZggQ1gQzw2RLlEpwPUBrABbMjHhiiX6JBKHuESBTaADeHYEOUSPdq9
sHEe2AA2hGNDlks0k9pAbQPYADZkYyOIcoke9Jh62L2ADWBDODZEuUT7XOxQgA1gA9iQjQ1R
LtG+J2xMwAawAWzIxoYol+ihjGXADlhgA9gQjg1RLtHeYAcssAFsyMeGKJdof0BtA9gANuRj
Q5RL9JDGYcB7UoANYEM4NkS5RHMZUw9zObABbAjHhiiXaJ+KGeDbADaADeHYEOUSPaqNHtgA
NoAN0diIslyi/TgOeLoXsAFsCMeGKJdoysN0wCQF2AA2hGNDlEu0eDwUENgANuRjQ5RLtPdF
D8AGsAFsCMeGKJdoGkfdK2AD2AA2ZGNDlku0qg2spAAbwIZwbIhyiQ5DOYzABrABbAjHhiiX
aDlMYdLABrABbMjGhiiX6DCS2kBJFNgANoRjQ5RLtPRQG8AGsCEeG0mUS3QopR9h9wI2gA3h
2BDlEh11GUY8FBDYADaEY0OUS/SoNlDbADaADeHYEOUSHfpywHtSgA1gQzo2RLlEx1BKwdO9
gA1gQzg2RLlER0WTlAJsABvAhmxsiHKJjmUyJQEbwAawIRsbolyik5ry5IANYAPYkI0NUS7R
4+uV8MZ5YAPYEI4NUS7RcZh0wVvZgA1gQzY2siiX6JjKhJUUYAPYkI4NUS7R3hWF520AG8CG
dGyIcokSNvCYHmAD2BCPDVEu0ePLHA2wAWwAG7KxIcolehjxnhRgA9iQjw1RLtE+0iQFG+eB
DWBDODZEuUSnQ7EFj+kBNoAN4diQ5RLNRWFPCrABbEjHhiiX6BEbmKQAG8CGcGyIcolOfUlw
iQIbwIZsbDglyiU6HYqDSxTYADakY0OUS3TKY8HrlYANYEM6NkS5RKc0HkY8bwPYADaEY0OU
S5TUxjBmYAPYADZkY0OUS/SoNvC8DWAD2BCODVEuUVIbPdQGsAFsSMeGLJdoX/oCbAAbwIZw
bMhyiaYxj/BtABvAhnBsyHKJVmygtgFsABvCsSHLJTpOdoLdC9gANmRjQ4tyifZDcSN2wAIb
wIZwbIhyiQ6uxBGP6QE2gA3h2BDlEh1VGbBxHtgANqRjQ5RLNIfR9VAbwAawIRwbolyiOY++
x0oKsAFsCMeGKJcoYSP02MoGbAAbwrEhyiUap6E/YJICbAAbwrEhyiV6nKRAbQAbwIZwbIhy
iSY/lMMB2AA2gA3Z2BDlEk2JsDEAG8AGsCEaG0aUS3QaJz3BJQpsABvCsSHKJTr1JeLJ5cAG
sCEdG6JcoimgtgFsABvysSHKJRrdEDPM5cAGsCEcG6JconEcDvBtABvAhnRsiHKJHuLYDyiJ
AhvAhnBsiHKJjrlMBWoD2AA2Pj82vrybpquhfFU71A3dBcP83Q/ffr180N+Nv77/y8Pb+3IY
H34s5fHbr4/3/FfUw4en6/n+eSiPtdM9fPHuowc67+X2gbriT791oPnD337hdEVwuD705frh
DzFPdPx9+YG+/v6s/EK/++GBfs1zUT9fXdMc5n6kzx7vn8qbd627eiz3x7YtsTeHX65unm7O
xqtpKgS8ihvVUZfXx1OzntK7Lzz+XL5s7rX/qWdDv2vMh3x8POg370/dRBeg3mr3Nx+mfjc8
PXxAtfrh27fXv56N5aEScb5754+//F0TKk2fbm6f+a3D3fvG3D7d9OV+CX04m2Faxm/eBPcu
ZJwZP6P7Ofj/4dfe3/38zO+8v9Nv/tA8+r7nGlc+3rj0p1TXvit89Lss+7vqM6mWS/XT4fqp
LKh6eCT+/0AQpj5xpPoznz3bhoe3h9vbuQm/D6Az+MGnx/NWv/jtt/VepUF4/OLx7oubq1vq
qtQh54/e9czfcnh/+93ROFPGsz9lt3pKzF/0lPSP96XsfkZWD3LxA2K8vzca3yxm6wV4fwbr
qWWctE/ejioeiaUSmnL8TMRJqbJMREPq/319O9yr28G9xz/5Cenpr2f99d3djZjWsIeEjzQn
vr45pGuHL/6plP/X65uTGjTncfixNkeFBu3Jr24P6dnD9bE9sUF7cLn+Uperxfn5G1+u17fn
tZfrkwg6wxV09tn8p+u7w+PvPyEZvJRinjsp8wHvz8kc+vqro199dW7ubu8e725pakttOjs8
DK9v1AmnLLHOVtq1TXWHPucSBgmX7+q2PJ5dvf3Jvb4xnn+KQu6sSryLt8TuegmN7nLmXcY5
dOcO1llT34TO6mXH2F2vrvGdzZrXviV21/PnVedyZjVvDt21dTZ0OUTHat4S2wAkur4PZv6k
FiWfrg/fvLmbvvrm++47+98vv+/+8W/73xN6aOe9T9qZEHJid9XOt0CiC34lk4sNmdhOZUrD
eq9C1pGHrHpQg0xifbXXs5lcbsjEdCZ4bbX3LgZlmXTrTGyQSc7m5d51fkomqrMhWJdS0Fk5
6mCsVOioBqkYFdZSudiUSjQpqBRjyF4n55mpRNsgFWvXUrnclIq31kZjkw+a/kMzU/GbUvm8
ov7jSxqOX3Nvp+HO3h7GsYy7DvaxLqZFHk2W2H2lnOliYo5AS+zeYi5FyxZzNXZfMRc65z1z
tJhj9xVzuqMuxZNLS+y+ci6RwDW867vENpFzeW3AdbN0cKfJuRCzCl4ZGnI972TTQS2kgwth
bbzdkAkpM0OyyngdbXCJN0bRQQ2GW5JzaxL7ckMmVZnRgEtKzidnmRqIDmowkSY5Z1/uXeen
ZFKFWUw5aO20DTryZmZ0VINUXpJzm1KJJvtEXcsb5YzdVc6pqF7uXyem4l1ySjmfbUyBWQ2h
ozzkXBs512AcPUXHZZpVMUtyS+y+Os523JJSjdxdw9Ftz9ZwFLuvhoudqg+A5Jy8Y+i+Cs52
yTIrK0vs3gouWCb/ltgWCk6v0fw7P6sFf5qCy1nRuORCNly5rLvQYonJhbUy1sWGTOjmTsEF
5Z1yKTNHWDqoTUFuTVVfbsikirFAGZiqcWlex1VwLTLJ2b3cu85PyYS0mFM2p/ooFquO7wjm
KbgGUzGj/ZqsvtiUSojJGueS0i7xq1ihhRi1YU1XX25KxaVAWlRTFkanzC2Tuk0dDAruGQX3
WQpyuUueWVBaYvcWcikoZkFpjt1XzEUa9njDyhy6r5QjgaEzb/xeYvcVc77zgVuOm2N3bZ+r
VGQufi2xTcScXhtuwywcwkliLhgfSP84q7zPzL5KwvTTirkNmZAu88EkT19rgje8KQod1OKa
xFWBfbkhk6rLsvfaBJuc510S09kW+jrntQXvpXOdn5IIqTJf6z46UO/SLvNkaV2SbSCAjPtI
7zoxlUAzbR9Sjk6F6LhaLja4Ksb6j3SvE1Op/oPoqZNRIlnxAEtHaWi512q5x329cS52/vi0
GM4INcfu7Y2j+RGzFDfH7qvfPKkey6xwzLG7Xl+d+Odvid33+tI5iVyFOcfuPX9wilctnEOb
6LdV/1KctUI8Sb/V1UejVK4uOeaprgc10W+r1ZJNmQTnojLBRGOVYxqfuxaan/Tbmqa+3JSJ
y9kYr4wLPlmeVNA0KjcRcGtL3EvvOj8lk7owSoNC8vVfHRNPVNNRDeqKxto11XOxKRXvlLYh
KUd3C1/0tCgrqtVb/nJTJi4bG5RX1gWaIqAUt6N8+xxVOFJmWTNdGUvs3rY45ZgqaYnde0nV
aOaC7xK7r4rLnfbM67vE7nt9Aw0DzJL/Ertv+1xneIPsMbKJhls1LaVZL6TTNFyqg2vKmaRP
4NbgdAs16sLaMuTFpkxIvSUbvXNOW+bGk0bVxLg+yG7KxGXrtM7BaKUM04+xcZD9k4Zbq1wt
vev8lEyqGstJK68V5cMvwrkWlav1yc7FplS8V1Fb+hGU8Za7NrzNR/bHVNKasr7cloryVcWp
QD8SanA7irh9DVOkyKJ1PIAssXvX4Jxn7jNeYveuwXmmY2oO3bsCZ1JgNm+O3b8C59n7Z2vs
3hU4y/WQLbGftgaXZ62QT6zBGa+Tz3RzaObSUKsa3KpR+2JTJqGuniYTbdaBOb7SQQ3G15dq
cJsycTmlqGmU9fr4ng0RNbg5k/NTMqk1OKtSvSI6ZM/e1tlkS4O1axflYlMq3tI8R8c6OdAq
clP51EW4Tam4lKN2Sln6ZqW5UhRVuBYC7rNU4VKtvDDXUufYvatwNmTmYtYcu3cVzjruWuUc
u3cVznnHLFnMsXtX4UJktm+J3bsK5xJzXWWJbaLkVs3nWs2ygf48SctlZbKl1nmruN7NNlsC
XqjFbcwl0ODkVDQ2m+C5GqhRNW5VzW3MxeWYlPXKaJ+Z+zqb6bnV59ksuZyflEutrdkcQla5
akW2l6xNRW61uHixMRnvbaJ/rPU6KOZUrlFNjjTxR3rZyckoSkQlp70Pmjma/l3LcvzHn58w
TDA7SJNpfrPNF5/hiXbMXQ1L7N41G625j/GYY3df782BvYW2xu56fav6Ucz2LbG7nj+Xu6SZ
j+FZYndtn61r9EwlvMQ2UZqr1nitF0WjT1U0wdlYVYDjTjzaKJoXHoSyKRfbqWqNr1tpVeRO
kumgNnsvVjc6bsrFdMYYHZNP0Sj+TtoWT9rJefVJO0sq5yelUvdfGJ2iMyHX/ZtcbWabrJeq
1aXfjclEnVIwLpjstfHciltscGVINX+sk52ajDfGB5rIKF33n3ONldtWZ6QLzf+bB9yRWvOe
uRa8xO5dwyExxFR2c+zeyi4FvrKrsfsqO09qlynsjqG7nj2vOqOYc9oldl9dFzvF3Y62xDbR
daurddos+sGcpusSKbpIuiR5w5zGNXKOubi6XLcpF9ORRE3OqKRMzswpAR3UwpkYVyu7lxtz
IX2ldNIp+5iZ1VASdi2KbsdXMbzYx85PyqVukdWkgWzd7xwzc7NMo421Wq1PHrYlE6tItTn6
6h5lP+euha574bHFG3Px9JXeWRq5bQ6Wrevw4OJGuu4zPOmOuetuid1b0AXHmynNobvLOe4T
YEP3PwAAAP//7H1bjuQ4suyOBKe/SG4ggVO5//1c9xALuDh9mG3iMFmPicJM94+pKyykEI1O
d7O2ow3kmZhTsEXlhp4Vc3xVcCbjhp6WcqIOOhXf2C1Sbto4X0bKQXkYPVGKxXqX1q4KCvuy
eBqEm6MscZGrCEvhRkqNwWmovGiLlJuVTj+XuIQqK9bcMhGkEjgws6dGxxn2/PUz9vGIC2Wm
Ts++2zStaeCxSl61gQzbvz1kT8m4Z7tlTwtmc7hX0XekaZQ29cReJKOVTNxIeucK+q7nVW8t
t0nL/SLPu65gR//Anu4DUwVV08CeFXUvHxmwz+/GnpV1WTkCx0Vf0LOyTmKTAC4CA3tW2LV4
okDPu4HdIuzmHVgj76A8DKGITyZCXXpBj+LLlj70L89eV7jIRRp6LqSQxb/gULE9tinTkcgl
KlmiK9rZQnR32JlyS/Nl6LrpSNDg8vGISyg0ac1jxx9kQnLDum7HrAPrrHb6Y5GMh0LNnjh3
pSroDPEmXTcvBK+R0Rb3w7KfVEnAlvS86q3r/uPRjfP+d6AUuaFnlRzHXwkqkRf0rI6zNHMA
ddyNPXpvQzt2RZfuG3v27lo+UPDkbWKPd3GCleFNkQelzNubRuZBeRZEUbSFjDMic0ENfq6y
Y1r1q1mNNS4uUjo19coNTDDZNqsxzYZd5JKHX1bIunfQXrEsLq//6KCbGvMMKh+PqLzyxNxY
zSppZVjFffPw7SIZk0pOlXuNpwyscWwav/0ij2KRjLbam1rh2GMKXGp8D+DuUHG/aAA39Dqo
5m7s6bNW/Kj1/Ekr6iB4Q89KuXY5oSXDG3u65OqOxmLe2NNSrhWwCWhgd8g5njc1jdSD8iyK
omg3j/c5tYb6lO2Sc3MblUUuro1KqFJVFoVHb/cYqczPwda4aC2hF5ibUoHvy9ox2D+qcnM9
N6IPHnFJZRZMiolxRiCgtZ8thsZfjd6ukbFMCWFrobeNCZ0j3nFkwDy9M5+LZOLHH7fm1T7n
CieMrc1DvfXcr3XEa6jB+8Aer8s1MPVsYE9X5szBZuyBPV2ZS0MAtDKX2NOVOe3g7ndgj1fm
pMCeeIn95urcCEEoD5MptBdSM9LqfljOzWcP17i41PoaH9CqYLbYtmyKeXVujYs2a94oNHav
sMPNjg0rv3IXvnzGPh5xyfKcMnn8yaxY1K5DdkjT+ejAj0UuJlnLltiLxMMGn7GujQ78bzI8
79BcIxOSNGc6xFuJXw5aanyfse5Qc7+oOicOqvaBPV2d64ba493Y0xU6YXDRH9jTNboKt/Xd
2NM1ulZR+7kbe/r5I7RxbmC/WdSNVITyMKoiXuyx4lKvVhy2Ov7uGt0aF1cX7mKdqBAs6r67
RrfGRasUEY33Qiv40PF31+hGMsIjLq8anTYuxeNrwvNJ99Topkm+PxbJWPzhSpW6WgcjUTbV
6Eqbq7o1Mho7htg3xH85XgC4a8lfWaP7Fns8tIM3cBteQ9smNY4b5BXw4buhp8s3jvpGvaCn
dSZ3XGcm9ui9zYguRouvN/bo92eZBA6+xgf26OeTPL4HW+cHdovOnJuojPSG8jC+oXnLQkie
Bx1N31KfLZo/lqikAWbpJVZMZ+5gvS0v2iIz54d0K1xyhrZIMCELaSYnB2+/NMcbAQ6PuKTN
HUlRy7a+NJY7aY5H0264H4tk4odSGvd4XzNTgU1UdhQP2eZjQGtkjEU8fis5o4W2yL/N8f4C
czwBj+UG9vSxoQsozwf2tLJrBu6WB/a0smvgsNUNPa3rTBjWdYk9retaRQdvb+yWHr+p2wWP
GAd+GOOQbrQ1dj2lEhrrt6VO9dXg7RIXvnpvLZ7T3rUxqutoh39znZZ1PxeplJbigT2UXevY
1nrP4G3ouqmv9uDy8YhLKrTKmROrVFgrWqTa4o0nMtV1i2RCnFbK1sHYYgmceLtF14lPzfEW
yZgQV888Pm0EOzi/zfF26brj5nhewJGpgT19JNeawEfCiT0u6AQ9cr2xpwWdNHQs4saelXTZ
GweOUg7sWUlXL3IweXlgt0i6qdEFj7wEfphjoa1T+uQxkaPJXLpnCnfaUb/EJR4C817EJHQD
g1FFcdGeHIupzcUSl7QuLo2rZsxIAwfTdtkdzyXdSEt4RCXEGYX4sR6bBu0K6tO4akMN9Ssv
lUUy7lVfMw5FmoJG1Ju8VOhfH7KnZNTNWIXS9Q899np75P3hHnmNYh8LrvwDe1bZxWpZ0YSy
G3tW2dXM9gCrHzf2rLJ7+QY+sBg8resa+Ka5oWdVXbsKaq/7gm7RdNMWLB5ZCfwsw8LIVbma
pX5AZzc2GR/Py3QrXDJmrMXWg4W4N7BlMS7aUXKs0xHpzyUufIVMJNPWQmuzwAZ5e9r8pkf8
g8vHIy5pkEfGzZlacfTgJ6/aIurmdbo1MqF9REXjOeuCWlJvEnVM0wmhRTJaXayE2CaKnyNs
rfIe3vjPhzeOG+TFNgR2yEvsWSHHVxO0a/7GnhVydlkDPWkG9uj9zfFaNNBtYE+fqTc0WGFg
T/dyFvjz3dgt3XTTViceeQn8LMciVFWroYTJO/o+3za1MV9p17i4NZfYUcY/DM7k2NEr8tUo
7iIXbTn02bUbEejfsW0Ud5qVMrh8POKSU7XOr/hfCu0AV4K2OOXRfN57kYypFskGVOsFNR37
fqe8RTLaaujsUKXOHX3M3k55f7BTXqzkHXvL39DTx661gK0/A3v62LU0dAznxp7VdC32Z+Ck
9cCevb9+VQdDjgf2tKarFbTdfkG3FOimxhc8khL4WYBFSM1OUtOchgpsrrIlwKLOD8TWuLhJ
Jy1qQQpM3Ns1hzvtb/xc5BJCu5OxVRVBHTd3zeFOQ1IGl49HXFKbWeMqsWuIZw0fkNghT7lN
vY8XyZhlEVhZ4+44PCDx3XO4i2TiZy8lNg+mhdEWnL91Dvfv9sprV+xDQK+8G3u6QNcNFCMD
e7xAZ+A45MAeL9AVcOP/gh4vzxX07t7Y01KOOpqxcWO/uTw38hL4aY6FVurdiM3ApWmbmJuX
59a4uHXpltWGomC/+oHy3BoXbVqk1NqaE5jlvifIIsTcvz1jH4+45HxD711z21Ae+B7vccqb
a7k1LiZ5PsnN3BnNN99UnfsijWyRTGzQK7HEyiO1gHNE78PWP9opj8HyyA09veRrAfd6A3u6
OicFbO0b2OPVOfDTJfJ4W2RHR3Bv7Gk5l6OUqJxL7Jba3LxbfeQl8MMci9ibC2tXMnT+MC/6
Zjm3xsVDycWPSLkVuOi8Sc59UZtb46JeG+W0bnXY7m9PaW7qKvfzEft4RCVLc5wSW7gXedXK
zh22iszrv2tkzOMtXUpo3tq4wnLuu0tza2SyNGcubG7UYPPCv7M0x99hkQeag50OZUAlyYY3
4wbp+4ts+xj0aL+hpyuZVMCRv4E9Lnz5gfDlw8JX0k8XtGob2KPfn6UrAvg+Htijn0/qxWDT
xg3dIn3nPf0jW4KfZUt0aVqsSvde0VfitcWC8AvfviUuchWqWS/jUFraMVWyy7dvWv37XOLC
FzfNMW1Ps2u0oH/taGwJ7Tu3EBrREo+4hMJKfxeX5qaK5gvTlr32V759i2TyeL2Icd4eUlTI
7/F3mdZlPxfJmOSkVW2tFO/wrmStLvu7a9//Kt8+btjCOrCnhV3s9+Ej6sSeFnatG27z0td8
LteFnV6lVXDTdWPPCrtyiYObwoE9K+z6VQQs+A/sFmk37+8fCRP8xPs/djzp2mXdyaijQdfX
jt/SlyPBK1wkw8EL3R3xaPtFXrSlqjk3VVu7L1LiiXbLLj0Gjw/jog33JaTd3Epo5Es84pLF
s9C+hYVbBRtBV+cU/iHs5ruHNSo1889iF5QqtYEjjHHVlgmSaYX2c5FM/k7i56LSu6G+36sV
2rew+x2M+wgslQzs6XPComBT5MCeV3R4xkY7nbERKi191VFFl9izik4vaqDBywt6XM+Brl03
dIuam/f2jyAHfhbkQMKVJP4pL/MYTMxtOaL+wrNvhYq8fO7IY431YmA5SLYY3YWYm49qrt0W
yVP2ENi119YOi7m5h9BIcXjEJYSZxF5GLW4L1YrX6XaUtorNfi8/Fsl47cGHrRfpCs/Q+p4K
6nzLsHhnemneQ6AGHSqoneJ7IHibnPsVdbpQat3BVX9gT6u65nj3V2LPqrp6WQXthAf2rKqr
eWYOqrobe1bV+UUEJjAP7NHPpyVXX0y1D+wWZTdt9JcR5SAPoxyK18rcObQdw1EOe+p0U2m3
xCW2bs1juY0VsAYl2I55RyxFnU5sfy7eFzEyVRWv+G3ZEzY2Nf39+Yh9PKLyMv0V0k7V0/EO
NhTZYnbXpgG9i2QqkXItOetsDfRUzKt2kKnTGOhFMlbcM8ellJdfNlqoeyen/cfK7rxznzN4
KjewZ9VcrJCEuoDc2LNqzuI7AZeUgT16fznt60G1NLBn769dFayC3dDTewntaDPnjd2h5WTa
5i8jwkGeRWsIvQpbItUcdMjNi3ZouTpfZ9e4uDZ1jx967QJajm5zeZk2+S9ysTxA7i29Xryg
Q85rPf7/EHPTaaXB5eMRl5Bl7J5W31kNgktBe/rP/u0Re0rFlCqHmms5Fwy6Im2aC2aaloJX
70tPa8iuafXN4PT5u0j3R7v29QbW5wb2dB8dKToZfGNPn7oWsOf0hp7Vc/H+bw3Ww4k9e3f9
MkH15o09+/k0Fh3wQOwF3aLnpq3rMuIb5FmshogyeW1WQ9TBem7PZPDUIneRi2vmi3WhkA3g
ayEv2qLnpoHzi1ysUKEszmkT1IZ5R9pJyLnpBM6g8vGISggA7Z1MWial4em3OyJ8MqX2X56x
p2TMhJpQ6CAxdVjQ7SAjfXrqukqGenxF8c94ytDhKFp8zN6C7lea9tWrCjhlNbCna3OoNdcN
PV6ZQ2fUBvZ0ZU4FrS3d2OOVOTROaWCP1+Ya3r2Z2C1abtqrLiO7QZ5lN0g8eJZRB8XcUNO+
HZGkX9bm1rh4Rop1z/M8BQ8VDtTm1rhYVhiZ1GKNBSXDttrcdOZmcPl4xCVrc42astVGVPFG
re+dDv2xSCb2jCXUHJc0YgaPwDdV575ooVu9M/GIlV6kSuEKTp+9q3N/tGufgPWHG3q6Npc7
PrQ2l9jTtTlRtOBxY89qOk7rbPj7S+zp6lwz8C0zsKerc5VA38OB3aLppi3rMtIb5Fl6g5ia
UyMPKQTXtLbUGr+qz61xcRVSqkRdcSuWTfW5qRHzIhcrxUKcdm+1wtZ9mwp08xrwyG54xCVL
bZneS57RGui8yib7kjL1IfyxSMbijyt3il2awZ2AW6z7pM53DotkSvxheuWdONwJ+HcW6OQ7
rPvAqsmWl9C2YY3jJnnoOdcNPV27yeRNtHaT2NM6kyvobj+wZ3VmvwzNWx7Yo9+f9gttgb6h
Rz+dpK0heEY9sFtU5rx9fsRKyLNYiVaaFbbM+jDQjjsu+mYnlSUu8RN3NpZWxJnA4ai8aIvK
nDfPr3Dhi4U9npmmFEIT9cjbUWujMh3vHlQ+HlF5NfWVWvIQszVT9OB0U+FwaqWySKaWVP1M
8bshtHU0rtoxFf1yXP3yIXtKJn4tzMS19qzqwtFt7wmNXXLuV3nkgecqN/R09aZ3dPL2xp5W
dbFgwnYqO/b9z4yPGa19DezRb8/oYtC+9oae1XT14gdDy3sSP6Yr1P/ISJaQZ8kS8czF+7yo
eWugdMiLttQN58d0K1z46k07ey1kjcCBgLxoh6KbzjZ8LnLhwmoUz7SHCoIl3Z664XyuewRL
POKSjX3NmNN9xN3glIwtjX0i823DGpkcUK/ZbuANnqDZJeloLunWyJhYqx7PGWn8at62x8ft
VI6u97VnoRh7mQzsaTXnDrrPDexxNYf60AzscT3HDAdZJPasnuOrMXiWPrCnFZ0p6sN2Y79Z
043IBHkWZRGaTkr8PxMgBO0j26PpvvBRWeEiVxEuFKttL94wSSd7Aum+KtKtUAl1xtaFvfXa
O2jdvKtKx/Px7pGX8IgLXRJCuxWR2lwFbu/b0Y8d3+K/PWNPyXhwiAesU5fq8CTxjubj7Cj8
l6fsKRmtnNEvWrKAWr/X4eYt6X4jhzywSndDT/eAKdjHc0PPqrpcycHz/YE9q+rkIrhKd2PP
qjqJWwaq4oE9q+pavKo7aMF2Y7eouvl45EhLkCdO9iHQGvXWWyiIyqDxcV70zWevK1wykEJj
HbfuISHAquOuFIuppdznEpdQaCTp4PyKKSM0XWSHiXPIunmH30hLeMQlZEDhSqVnNTgeNrjD
b0fZkXV2Y34sknGvnaVWESa0JzbtkneUHb+YDVq8M00sDRjry+0PvTFLv/63qvu17niG9oEN
7FktxzkNDh5I3Nizas6uWFbgGdzEHr2/5XVIDja139iz9ze+E3D28Iae7uIsHSydvKBblNx8
NnJEJcgTE/tysWm3blo0tBw638DfPauxxsUlPTsKBRN0NHrXrMZ0ZvVzkYs2764hGBQeCSqb
Qrym2Wo/n7GPR1xSk8XT1cWVqT2Y1dih5L6av10jY1LFiqvHD6eBv5hN87cyzc39XL0zaXBD
WQoOmQ0nkr3nb3dIuV80fwtW+1/I0yeuijYMv6Cnz1uzzxw2xrMdv/iHfiro6PILerrqCvZA
BfC0imug3+EN3aLipo3qOlIR9IlhfQiy2I0XD40Zb/OCuqjwhm+6vB66/3uBXeTixhl77p1E
0M3JLheVWbfZ5yIXrY3JQvxkkxY6o7LDwz1U3HSqe3D5eMQlhyHM3LWQUEfHh3cFkc0t8RbJ
xOu511aqxc/FGto5t8USr7RpPW71znSXJtxaPmd459xS2fet4n6xJV4DRcjAni7IOaOmaTf2
eEHOQeODF/R0OQ62ZXhBjxfjioIK88aeL8eBIvMF/WYhNyIR9FkkArul0Ui33tFz7G1CblqO
W+SS5TiK1bVVxQd0v7sct8gldbV06VVVYG/jTeW46cHq4PLxiMvrYFXJuef5fQHf1rsOVqdT
Az8WyVi6GteiElsGxu2Ad6hSpqkd3uqdiQVbS7FMJShgD9W7HPdH2+EpOrc3sKdLcl1RPXdj
TxfluKEHrDf2dFGuMlrTvLGny3KtoUMuN/b080do2scLukXTTUcOdcQi6LNYBI776sStUwXP
iw/U5taouJG5UCy6jfG0iu+uza1x0dpJxamG3oZTRPbU5uYOx4PLxyMuWZurvZOQlDwt/m1q
c2tkzIxq1SJWM7fipBveV7W5xTvTq3QvasylVJjMX1mb+xY3vAIOGZYdA4Z/sB8eGtN6Q0+X
bhxd5l/Q4yITDdJ4Qc9KzLhdCn68gT367Vm+mQl79Ab26OcTv4qi1ik3dofI1OkQpI68Bn2W
11B7dr5ZK60R7p2yJePWp05lS1zkKhT6shW3XgthS2ZetENlTsNUP5e4pA1Kq967NlXqYPLe
taOPmomnjouDy8cjLqky2bhXa3HL0dT0vGpHrW1qH/ljkUzc6njIJOSyKIMl3bxqi2Se9vEt
kkl12TMFRl/T9m87vNNq7hfZ4TlqoTKwp08MvYDDjgN7Wti1AvbMDezR+yt4S5+cb+lLsWag
8BzY08Kuu4Gjyjd2i7Cbn9aN0AZ9FtrQCpOlZau2Dm7h8qItwm5+WLfCJefBXZzVao91Fx61
3cHli1HbJS58ld7IvFYN3Y2W0HeN2k5NegaXj0dcshBYayWn2oIRSCat9LYcok7DNBbJVHYh
Lto7czN02mSLsBOfnwivkXmNM2kvrCpE6IDG2vH2W9j9DqZ44BN7Q0+fxrWOjtve2ON6zkD3
/IE9XarTisdWJPasoku3MvD+DuxZRVezPQ53Od5ieZiji9PVdgQk6LPgiqotvfCqSrzTUfOU
+s2WeEtc4iFIM900X6PWwdOtvGiLopsf1a1wyVJdCLrCTZgUDOHaZXNM856DkY/wiAtdUvNs
253NyUGpnVftUHRz85RFMmmekmYj7hb7ILTHb495yhelujUy6k2JO3vxSvCB8NsTb5ui+xWl
ukYXoZFQA3tW2tWLHPSLekHPCruabb64K57s+PaeFOo4ljTw8w3saWHXCRylHNizwq69jMtQ
V7zEbhF28wnJkZOgD/MrRJrUtJGDTXXzom8u1a1wkYuqcivUcrIQ9TreMZFU6tSx43OJSvze
auslxEPPUzI0imPHWUnp0964n4/YxyMuoQOoaG89PUhqA9sq8qotum72e/mxSMazv49i98DG
BcwN36TrmOYTQot3plYyKtVKv+uAb1e8Q7ruvCteBecgb+hZJcdXvLPhEdzEntVydjmjRmM3
9ujdLT12aGCg4MCePlRvFdRKA3u6l7OgC9PAbtFy816nEZCgz3IrWC3+Z6HjQs6hx66bfPHm
6+waF890+VieiBmdRipbIgW+HMRd46ItA4lr7bFHBsc9tzmqTF20B5ePR1xSllXr6rVYKxUe
2thjizcvBK9xsQx5qLWV0ECi35ve9WAOd/HGNEv/gkLZvAn+Yt5zuH+wLV69Yh8CGx0n9vTJ
ay2ghcLAnj55LRVdWW7s2ZPXfG3CY7h6uk/Sr4p+ewN7WtLVDpYPB3aHpPvCW2WEI+iz0Ap2
jmW2Z5GugHWgvOibJd0al5B0meDVJN5F8FDxHkkn89V2jYvWbDwT5tLA7oOyeB72YA53JCM8
ovKaw6WQQBqiIcPpT87hyhcTEmtkzIlaCw0kNRQdSubb53AX70wPJRevzhB1OVr8Xz2H+7d7
5DUCCxADe7pA1x31Ubuxpwt01sHvb2BPF+gM1po39niBDmxSu6HHy3Por2Ngt2i5+UI74hH0
aWyFebdWuIV2QEXDt2u5NS4ePHrveUzZwBD3bVpu3t20xkVbqeTeC/cK9tBtK8/92zP28YhL
lue6meRMdWgruPd+U31uPhWxRiYDokNid+V4YYNzRLtiK/p89mbxzrySB3u2GmoBq/Pvs9Y/
2iePOxpEdmNPr/kq4ED8wJ6uzwlY/7qhp6tzogJ+ezf2eHNkJ7D+dWNPa7qOOsC8oN974Goj
KsEeRlho7M9Zmsu9+/8tDlwXubhTcfdWqSv9LtW5RS5aQ1k1ZpJK4GjorvLc3MBkcPl4xCXL
c4UtRJCIFJTMJgOTL8pzi2TMKTS21ZB0XGER9N3ludU70zPll6hp1wJnyv6d5Tn+423yHkkT
UJZseDlu0L+/yryv4T4viT1d0SQBYx0H9rj6JTy6LbFnK5qkV+xmwQ84wEe/QSuXNXD/NbBH
P59SelZiT+DAbtHAUx8OGykT9sT/3y8taVrBscOxAobS+RZ58tVk8BIXuYqLUYYZMIGzMHnN
Fgk8LTctUeErdibdS3OTLJ+BAySbJPC0CWJw+XjEJX6bhXrGcJBIB9/ZedEOLj6N4l3iQtlb
b1xT/sau0dAQtx0+WfFXTo0iF8lYI+ves6Sp+GTPmgXI766A/5ss/CqYcH9DTwu7WtDC1409
Lewa2p47sIeFXfylFR12GeCzwk5yOhIUdjf2rLDTKwMNMGF3Y79Z2I2sCXuSAhB7CvF0r6Au
maEKCrsdU+JfCrsVLi/Llyax5EqPnRLor7jJ8kXmZacVLpx5JqpdScwZtOLhLXkmoeymli+D
y8cjLiHSJH1kQjo4K6O2QluC0GhadP6xxCU0mjN7xu21ksG2qLLbUdt8HZR9+ZA9JeNKjTKg
W2ITAUZU0mIQ4lvZ/QYefooO4A7s8Q4wBathA3ta1HXUDGRgz4q6QldDD8Ju7FlJ51dBfY8H
9rSk84bOWt3YLZJuOrxpI9jBnljue6ZUWbzUW+WiFa3VbfGY1joN3FjiIpfEauul1GyQR7NQ
rh1dGCHpZvflc4lLqDOVoFGNuxS4WLcjdThk0DTUZXD5eMSlXNLVMnKD0xAMjduTHanDPJXa
P5a4hDijPOEtZtK8gV5jcdWebsp5RXiNTGwXpAoXltZR47TVs/e3pPt9TPyKgcpuYE8ru6ag
ffTAnlV29TL08w3sYWXHV+8NLNcN8Flt1y8xcLhkYM9+vleUAKg9b+w3l+tGtoM9cd33S5U4
w3qFCM2G8y1xCKHtpkZ+S1xCpjUOjcqmwg1Mhs2Ltmi7qfnLEhe+WlUPPeSuGjoC1HZty0Hs
1JXw5zP28YhLyemSUKlVyLKLD+2r3HMQOx0uWeKSR6oZUcNkmaYGnvZvOogtZTrCtEjGX+bM
LY0oCT2ci6vekRv/sbY7b+TnaLz8wJ7Vc7GXQ8ciXtCzas7imUfTNm7s0bsrLRQueNY2sGfv
rl/U0TrsjT37+fQqaEjXwG7RctMpThupDvYs1UGb5oRHc/UCzmLwlonU+FvnR68rXHJEJP0c
zbs4GtRStvjlljp14/lc5GJxW169TjVWWbS2tWUedX5c+fMZ+3jEJWv81tMAT0RZCT3h21HY
jm3KXMytkTFthUvsHWuxCk9i7DgTF5s31S1yIZfQ2VabddQniRbbHd9a7jcw8msXoScYA3u6
o45Q0TSwpw9ff2sjP+mxPUOTIm7s2ftbLzbQPXpgz36+NOzB3WkSu0XUzbvYR6SDPYt0yKat
WKNCBxGBh69x0Z5h4RmXH0tcQp81tVj6iuVyCw8L7ynQzXrQPhe55ORPcUtf4wImHZbFHvZ/
iLppmsvg8vGIS8ozFVYnU3OFh4W3iDqu82HhNTIZfxJSsXSn7uALNK7aEqHG00CXVTJxX7JX
gS32QuBg5DsU98/08quKzvXd2OMVOjQQ9wU9XaGz1uGojcSevbtySQWtqAb27N1tV2yEwQrd
jT1eQURPgwd2i5ibN66PSAd74rbPV20h5e7mIPS0NS/aIuZmXH4scSlXo6zPaanU0ez5vGiH
mNN58WSNi9cipYsW6h33Jdxz2jp3fhmJDo+40NWpxYZBlTz2NOBIW1y1p/tsvmNYI2Ot9R6r
iXqzVyobpn929AWWPvcXWiSjVkvOR1T2qrDL9NJe7i3mfg8vvwqeew3s6RJdKA24RJfY0yU6
PJHqxp69vznTgpUxbujRb09itQXfmDf07Kejq3Rspb2hO/Tc9NDlf2zkOdgTq325iKubU2gH
bnB07JYU3DY/C1uhUq6unbMAZELMaGRI3zLrqvOqyRqXpi1WWm4tbw6cTrxl1nU6TPDzEft4
yIVe2XwvJ5OmaPPcjlo7yzQz5McSF7pCkXoJpS3KbGAxm7a4RbJM7WU+V8nwaywqc3Azb/C/
unlOvsPHD1z5dyz6f7JfnoGmEQN7VmHKVRiN6L2xpxUmN9BA4AU9encLpcIAyxE39ui3Z5QO
0NivdGDPasx6xWoD9kXe2C1Vw7kEGEkT9iQDIDY2XKV71qiqgeEMuRvaITN9PqOxwiWe0eos
PeN5u4CVtrhoyxEwzRXACheODXvI/kxPpWKgDUlctOcIeD7jPXImHnHJYJKap/PpslzBzLCy
GAP7j6LhvDK9woWuGmqv9tiVccsDbXRGY8txNs2HvNfImFiaRbuKesej6d6WKrsE3S8yy7MC
DkQM7Fldp1fv4HnrwJ7WdQ0vHLbDdcM0Ni5oN8dP8GllV8GBkht6Vte1+CtBo90XdEvtcDoV
6SNtwp/kALw6SmOtFVatsOX5teM5+ErVLXEJgRbbj1KbeIPbCPKiHaquTM+Cl7iEQOtN1aVr
enegDZey4Vz7K1U3uHw84pIC7cVFGmsHzwLKYtTEP1xVpn19S1ziLSMkVEWqlNsXCFN1O1z/
2KZbh0UyZtXJha1wdzAY4u2q8gcb5QnaVzuwp+WcK/iqe0GPizllNDzlhT0s59rVDY1mHeCz
ck4uQTfCA3ta0HW0vW9gtxTq5svtSE/wh6EW3llaDbleGMxI9C3pCV95Hy9xyYCKGpKh9JKT
uNhqm67ZW86Dp41XS1xCnRVuvZLFRq+hPnmyxX9k7pM3qHw8olKu9GLr5CWUXQW55EU76nTT
rssfS1zo8hqyNIt02rvDzX172i7Lvz1jT8lop97SllriHQAGCNFiBfWt6H4Tn7wQaw1sMLmh
Z2Vdxiw12HcjsWeFXb0MPd58QQ/Lun51tD3yJ/isrNOLUUOJgT36+bRcBJrA39Atdbqp44WP
4AR/FmjBVaqL1upu4JxDXrRF1E2daZe4yJUTke7ETEwOi7otMxvThNvPJS4h0FQt+yCV8jwZ
VXXf7H48uHw84pICrVGrvUtrr0EdTNXtOEkuPg20WOIS+iyWOdU8texZ3EZV3RYy067Yz0Uy
8YTFXTF1jR0W6Jf6dlX5Mx3yrIB79oE9q+X4MkJHBm/sWS1nl6Nt4y/o0bsr7cpVDy0wJfbs
3bUL7iEe2NN9nOKg2/HAbtFyU6MLH4kJ/iwxQWvcWc3ynHaUzq4C3XQ0colLuXJJCjaxzBJ6
a8qW9IdSvyierHHRbiKx0sZ/mQQdPtlyTvmFQ97g8vGISzrksTSp7FIE3HznRVs66eYVujUu
ptScQgFp5wY2Sq82nz2o0K2R0V5qLUrxc8mZjXeF7qCW+yXjtzVjC8Dx2xt7+tQ1HknYdjax
p89d4Xitsite65lDHhvYhDiwp8uvrmBvx8Cefv7SJwJ9/hK7RdRNDS98RCX4s6gE5WatF8ps
dPTrvnaMOxedO9IucUl91kg5VqfUdrARyZYp3DKdwl3kEhK7dc+xAnXYIObbRd1ISnjEJfVZ
zUDjYGTCYMl9k0Ne6fOj/TUyZpYhFmIUO6FvjvT6R4VuOh+xSoZUm2iLX3/8bv5/Mv8PAAD/
/+x9y7IkOW7sFymMIAg+fuCYdZ3PkLS4i6tZXP2/CYhgaqEWozx4cXCqanK6rXoWHt3pycgI
Jwi435LZus3equ6bHfLQn97ERlfoKuyhdmGjK3RSwRrYxEbLuYamRExstJy77H0xOWfY6Bpd
R89bJtZFzi2nXetMS6jPUizMjV8f6EyqhdCv2ylttq8k0I8tLmYRZ15/qksldUb7730Mj8sy
LGqTi7BSUSWXwSFE2rSh/ZuWW8akTCIfj4ioKrN5iEY55zQqOL5uV3mQudkw7JGR0lSaip3q
1wYewDhlWOS03jHskSljkO7kskWrocZpby33WxvkFQKPvSY2ukIyGsMVEsNGV+j0oQxKugsb
u7509AFKkomNXd92VAHTxic2+li4NHBuY2JdJN16LmJmJdRnGRZiIwS9ceMxwFmC7OLIT6fL
8uKFu8NF1dmQSkMFXRZ0LoKO5mN7vG6h2+Oie7zUTwfDUuFhApc60J2qm0kJj7ioPtNfZyo8
dF9TKxguknwSc3Nb92nukTH3QkvyUxWUCFd1LmMeda3qNsnkmu0QuUjnBz10b6M8+IeMNql7
9Kf/xlZ5urcALQUvbHT5pjbQrn1io7VmRmdIJzZ0fc0Ajxh0e3uBQ79Bc0phsEA8saGfj+uB
hghXF1PWO6u8OoMc6hOL/WpDAdQtazX3BE60V5ehgNsJ3B0u5oaZWuLMqcEHW3aRi9Jcrcvn
FpesjwMhos65tw7ay+lFPkpzvZuZMQ6PuNi5dhKVmc1KuoyqZhervFRXRd0fW1zsIcM5S2KS
NgbYXu5kqsLLyZPPTTJi1j2qMzsRF3Bl/lSh+c9klVcz2OU3sdE1nCrgYMnERuu6nsE6xgkN
V3VC4IPpBQ5XdeDyXtBYTWdRgaBV3gl1qR+uazszz6E+sdqvB0muhUaiwQSOrdpFLqpubZW3
w8Vc71oVFXVMlzTBrPJ8VN2692qHiwq0osIhpVbyQKvoh0ey4a2om2kOj6iY/3FtmXvqlAhu
vHQSdesS9Q4XczIe1O2cXn826LPTS9Qt67qfm2SkWEaevhWTClRY073tj500XbhRnqAHwhMb
fSDc0ZGIiQ0XcwK2tExssJzrJoFwq7wW7qnCdsyLfcCJjRZ0+q7FPt/EuhTq1u/bmZ1Qn2Va
FJGcRHfqxKiDkvnrfXGhbocLH9SLvm+Fe80ZzIFgHyfnM0V08brd4WKFOjtnNmvqlGGvPI9N
ob7lVxPSr3vs4xEXOixpma2wRT2BP2knr7y8/L382OJirnel24RdKSSVUfdjF6+8nH52kz0l
U/SxnmodPSX93cCTuFu/mLeo+3W88prg2s6w0c1gqYAHYBMbq+3aIYwaPVzYYG039IcN9ne8
wLHarhyM1lwmNlbb6Y6mojWhC+tSrlsOS7aZoNCeJVvkkiVZ8aF21NW5utSF7hzztricjnkl
Df2fNcqhEb8+jnnrQ9gtLuch7OCkC677UrSr2esQdumYN7l8POJiMi232kfTDQQouZ2k3Y1h
3haV0zBvZKJWzdsZPIpxMszThfnJPfaUTBk1jZJEtXeu+T3CEWmyEvq6P0dsQfeSiY2Vc/no
8OzGhY2Vc3JUBj/fxIauL3drDwcLTRc2+lxdH//wubpho/s5c8EEwwV1kXLLEkqbyQntWXKC
bnLqYEqiWh0cYPUyzGvLXqctLmaTorIn5TKYG2gbRD59jo2WFZRNLqU3q52chUewpdTruHLt
rTK5fDziko6euu4WiKW0XBtaDfJxzCvLie9NMlKUQ8p28KpiGx528DgU52V34OcmGb3LdFn0
NstFN3To4evbMc9DzH2XY14Bjw8nNvr4tcEWHBc2+viVGtiLOLGxmm4chD6UJjZ2fS2LF5wP
PaHRim7kBt59F9ZF063i0f9qMzihPQtOKJZn2Un/QYXRgFOPyedbTbfDxeRZUtnAo0ruqC2J
j6TLq2X53KRSWh+jWuhsSWC6MW2eiT2QdDM24RGX0y5PSi8iY5izc6RdHq+DZzfJSE3c2cwT
mlTY0dllTPrGYmWTjFmskBiP0QQek37X5xwkXbhdXj1N5zEtZ9jo+pzegXCghWGj63MCjgtf
0GgllwWsvk5stJIjNDz9hEYrOWF0H3FhPZRcXR+CzdiE9izOQqiRmbIVKRksnOhFLkpubZW3
xcWs8oa+ljIPaSPYKi+vD1r3uIhqBRXXQ0qpYAAebYZG/U3KLSNTJpePR1xMlHFPZuKsW4aM
+6q4SLllEPCPTTJSRh2plpRH6Xh1zsctb12d2yNTBo+SB6ekAhXcMbyrc7+1W54+6kFFd2Gj
T+QKbEB7YaOrc5wynGdh2Nj1TUcrqFvehY1ukMwNDSm7sOHVYfT3MbEuqm6lhP5qMzehPcyz
GCNLa121HRzP4ZKbQKUtRyO2uJiqy01IuvUqgpVdculap9MMd/G+3eMiVq/npjqVBpiFRS5q
+84tb3L5eMRF9VmpufeqYrs2tK9Rr/IQQrx0pv6xSUZqLTmVqoIoNdAO1ckt7yZxdpcM8ag1
J9K1QQe9ftfE2TjN9n//8R//+M9//Mf/+dd/oZT+5d/+/f/9a+irCVvG6MNKUAk5PIwdNPc3
eQbqbxD2ljFsdA01oe0/ExuvuGFvGYWGrq7uQWiA3Q4TG/rtSToygY1qExv6+bgefYC+dCfU
Q23TusNxxlq0h7EWpQz9K+WUGbVSd+nXuvOW2eLCR+opUc61UqvgRs0u8lDbZbUun1tcbO6E
U+m6AWoldTQGxmdYJa3r9DPX4hGXdHAlGqpQuatQBTtI7CoPgZp+dpM9JdP0C9LNVdbNot5t
aNnRo/s652V25OcmGckjNRHdCOVSMnwc/rYM9NJz32QZONA5y4mNlnWtopWfCxst60YCJ6Un
NlbYVRND6OGzQmNlHR0FfDlf0FhR1w9uoJnbxLoUUdcdaDPaoj2MtpB0iYeece8Pj4O+W1m3
w0UVWkksRElKl4L6y3hsVqitrT+2uJhCG62ptEvcRoONoD1KdSmtxMPrHvt4xCXZzd8kJ2Ld
GTJIJvlMId84QW+SaVyqvulUnqbSwJePk2ngOhXvc5OMNZ/2rv/eweO0vfzCc/63rPtu18BO
1n+HrfLERrebmR8n2m5m2Hg9B74jT2i0mmsDLFZPbKye48Mm5FDHQMNGKzqpYNFhYl0U3boR
bUZItGexC2LzBFQHSaoDVnQeXG4cA7e4nD9x1u+5MY1KaKHOY5+iim5dqNvhouKsU+IuVTV8
q7Ci85lbWY9GzQSJR1xUm+XOkqimklsGz/j1Khfn5GW6349NMrUmVUBmnJ5VaqMiyGOvnqn/
7C57SuacDZfeLUsbzTtLm04Eb0X3i1gG9nykhhVlL2i0rOuoxdHExsq6plIXHCQ8obGyrh+Z
0WnaCxsr60R3kWDe3cSGfr6i752B+i9dWJfz1/XZ2MyQaM+CF2qSXMhyPXpG7ZCO6pFTcifr
drioQpOmL12qjeBYbr3Ix2FmXULZ4aIKbZiiU20n+gc6Jc4OXag5lZ/dYx+PuCRLBUxVRFWd
dAF3usklFjCvLZl+bJKpzQwDKRWmDO4dnNwCEy0T2za5lKFfUNUtu767Ca7TvUdY/v9VXbxb
YB3g431iY7Uc6QMPPDI8obFKTo6aGWxOurChq0uqzwT1vbmwsaur30kBv7+Jjd5JlAxuaifW
pUS3PhCb4RHtWeACVUvRyqwvJzTFRy/ycQtcj4rucakqSoV751EbeOhqF7loubXpxx4Xmyhi
MuMPlXSotYzHRJFKhrWWm9kRj7ioKutZ/6piEa/4sAd76B/m9dD7Hhkz6Tc9pxpIBLTOd3IL
vBNze2SK3mBEo7UmujBvt8BIMfdt88jgwdzERrfR6a4PfKte2OhjVxpoy/mFjVV146AEVpgm
NnZ9q76j0HnkCxv7+YolYYCf78K6qLqVm8lffcZG9GdRC6T7867Sro1eBI1Gdak23qi6TS6V
pQ+zpWs9gycLbqpu+b7d5FJGlVST3tajgj6OXqpuaZv8usc+HnGx8nRtnS1NsZeGJ4J5kKHl
wvzYJGOVxsqVdZtWwMAmJ5MZ6suI510uic3/kPUfXYXd2y8wTtTF+wWiXQITG12hKxms3U9s
eI0uobECFza8RsegF9kJDa/QJbB56ISG1+fgIcQL+7X1uT5TI/qz1AgVcUyjDKn6B5qA8dX1
uU0uZuJmCRhDOixKv7o8t0mljFEL5XL98YuU5yaXj0dczvKccG+qs4duaNAi0FeX5zbJCLdU
VPV0/UGjWU1fX57bJFMGpWyStCspsBv9XZ77re0CzbAcLc8ZNro8xx1sLDmh0cU5BscgL2h0
aa5k0Nx7YqNLc62g4XsXNro0Jwm1frmwLs1zy5mIPjMj+rPMCOr6qhUqkrIkuDTnMUdwJ+j2
uFSupWeLDZWOVp2/XtHtcbED19xHT1ISaiLvVZpbTlJPLh+PuFiRLRebpLbkvAE+sL1Kc2PZ
oblJRoRH42KhZtLAlXGqzfH42V32mIzF5lEqqTUL8/mjrQJ/9jEYVnQPXhNg+7fLQ8htUiPc
Iq+CT+sLGl24IXxCg6IHNFQ4orNMExu6tqdJMj8wVPbYxj8ZgRhHP/2tkB3OhQ39fFwPAm1y
LqiLxlxaBfcZZtEfhllY1ZBLqn2AVQMf1+M7I5UtKnwk4VJbJhkZbLayazwUZlmmxW1RyUem
lvj0LORM8NStixn10r/5dYd9POKSDhZR/VJU/esXRegZo5M93nI8Y5NMozP5LulmrzRQQDjZ
41Ff1wz3yIidFliZnXvK4Gs+bf76f3WF+U9jj9dsBUHVNLHRxZsxGly8MWy0rOsVzxkxbKys
k8POaNDDVsOGfn+SDrOgQn2PDRsr65r+N8Fpkol1EXbrvr6ZZ9Gf5VmU0WqmITblOdBsDp+c
kb50L9viko9h8XHZ/NhSQm/tY7jkjMhy8naTCymZajOe3DvoK6TSzmNdxvjZPfbxiItJO+VR
SSjpX3AvnJO0WxqqbJJpSqVWFXg9c82oTvVwpchZ1o19e2QkSz4HT0isgfTtfBws7eIt8iq4
yhMbrelqBl29JjZc0xWw1DSxsZquHsTgbnNiYzUdH5nBA9eJjdZ0TOD3N7EuHX7rw7qZmtAf
pllYNlkrZpQ1wGAYN9vj9VndDhczRkmdmx06Cgn2tnVzU1kmAm9xsXKdtSlm64kr4NbQrVy3
7iKdmQmPuJhJXirUedioEcO+ch6boMxltTA/NslU1UGtFt026N+gabxd5dLitz4Q3iNTRHdA
Q7XiaB1sB9GLtn4xb0n3q3jk0THQLPuJjW4FQ0NtL2isrmu4y9vERus6EfjbE4/W42eqrsCV
ugsbq+r6URJaqbuwX3wEO0MT+sMwC2JWSVctRRctLG/2+Tw4g93hYrkUNdXUVOAn1DzT6xCW
1oewO1yytV9Wm1mlzB21F3Jpv1QFtq7UzciER1xMn5VkgcB1lJpBuR2g6vbIqKrTLZp53rDF
e0WqOh6r2vbnJplSbWKDeymVcMebt/Wxw+BGvEleA4t0Exsr5fIh6NTBxMaKudO6DRRzFzZ0
fakfKaNFxAsbu76iChK8/yY2upszJ2yE+YJ6iLm8npCceQn9WY4FiYU+9DKaVR7QmQ2fEt1K
AP3Y5FKZ+zB3iFaqwHYqDsPbKuaWyWSbXMoZ/ZDyUFUHjqLbRS7HruuOupmW8IiLZYy1obfZ
UIVN0kKncPM6cHaTjLDuGPQ74qK/GPyk0mMKl5cpNp+bZIo5ZPbUqrTWwf3Pewr3NzbJa8fo
YEfKxEYfvBbQ1ueCRh+7ZkLDni5stKKr5yEepugMG118rfAAzIWNVnT6PAQV54V1KdAtc6P6
DEvoz0IsqLRWhEu3+ExUO/houps53D0utaTGNiapnEB3T7c53GVq1CaX0s7Wszws8xGdj96r
nPytQLeSQa977OMRF1Nnut/vhe0EBw7AYo9i490Y7h4XkaLPGnOV1A1W7Bgu9fXZ/h4Z3cmV
NKRkXaEM+n2+LfJ+T4u8hpqCTGx4fW408BziwkbX59D92wWN1XKmvkGDvBMaXpsj0M1nYsNr
cwWcEJtYlwa69Vt2RiX0hxEWwpy6WF4UFXQo4suV3B6XyjXxmYPOvaJcnJTcujq3x6UMsyFJ
Z28jmoSzWTb5n0ourY/zZ1DCIy5WnaudpPViAfVw/9xXF+f2uOimR/+2ntPBGezz2R0jeFCc
2yNTeh0pcWtieWRvi7xIJfddFnkV7J2b2Oji3OhoV/+FDS/PNdSG7sJGl+d0twwfuBo2ujzX
OpqBe2Gj77/E6IHwhXURdcsX7phJCeNhgkXl3JsdhiXGc8k8uJS2Oj7+scmlFrHDI8mlw70E
Lp1N1PKyf26TS2nVJiKIqDTQ98PnyDWn8rN77OMRF6u0ZU612t5B7zU4l+yL63ObZEQkUWNb
GeqghZFe5TG2m9NyKmKTjKrT1Fpu3FJtuInJH1mf+xKbPNjDzCW20m1cI9wor6Ee4hMbXcDR
VwtcwDFsuNbsYP7HxIaur+ofwqUSBbfOSToIjWSd2NDPx/VI6GjDxLocBC/Lh2NGOYyHUQ69
qny1MM9eMtxE5mLIvJ7U2OLCh740e0v6+s8DrB7qNR5P+Jvx2y0q5/ht4i42dcLgYKTb+O3q
TPt1i3084qKSsdh4Z2XR26x27B4zIxYPoZmWJepNMqrHZNSu4qxI7mijootbHi/Nbj43yYje
uWXURDSkwHbMb7M8Lz33HSVElWqjYT/CCxp9aqjvI9jqzbDRoq7DFZkLGy3qekULdBc2VtZZ
6xl4Kjyx0bKug+60F9SlfLh+4840h/EwzcESzVPqmQWV+E6TAXeiboeLCjTulubLklU8wB7I
PmfC6/LhDhcbv21MPbGU8ygwcvp2ObAxqXw8onJaIPMgrmJTuPjAhkvBjZc+eZtkVGYPZq7p
HKdBNZ3PkfC6eLjHRXI1ElkFHRwB+bbJ+41t8nRHApupGDb8QLjgNnmGDddzoBy5oLFqrh6C
xjFNbKya44MaWIKd2Fg1147Uwe9vYl303HJaY8zshPEw0aLlOjpZS1lLsPGxSwzu2iRvi4ve
BFIapdJ7P//dmEeej5vKSjZ8blExC+PEuoHKRglso/fxPb5zU5lcPh5xOd1UeLROeaiaAw2c
3NxU1nuGPTLV2uFqL12fiGi7j5dHnix7/DbJFOFeKykXfQDAK1O2yLwF3a9ikpePlEBhMrGx
uk7flhU83JzYWF3XbCME1ukubLSyKw3Nc72w0cquNLCOOLGxyq6rWgOn1CfWQ9ktm+P+GjM6
YTyLtBBKzHxOfI4GzvJ8uVHeFhfzvCPWH3rRfzNa4vUyylt63nxuccmH9Q5WHkksfg38mepF
HgJi2U72usc+HnExkZZbb41Um/QKH1l+tVHeJpkqmTI3aSXRYPQw2cn+eL2B2CNTainJZjgG
EYPdF2//49/UKE/ApsOJjZVz+egCzh1MbKycs6NeUI5MbOj6qoTsjE75XdjoY/WW0EHrCxvd
y0kCendMrIecy6sH+l9jpiaMZ2kWVGyfPmoZGTbp1os85NzN3MYel1qqvmJzt2PXjnLxmdvg
dQ1lj0vpmfWh1dlGHlCZ7TO3sQz1et1jH4+42DBuMZ/gctXr0K4t9tCmulP5yU32lIzwKLX3
XMpoaKuCk1VeXvYGfm6SKV26TdU0Kr3hcRbvaVwHOfdN07gJ3IJc0Oij10ZotOSFjT56JTQq
YmJjNV3XnRZ4uDmxsetbj4HmdU9stKZrAxQOE+uh6dZWeWNmJoxnWRZUOBFZhT09sMrz0XTr
w9c9LrWObta0Q67uNkzTuaTOrq3yNrkU69rK0i3bFDQE9bHKM5vin9xjH4+4mFeKybleS5Yx
4KYtF4cVvumm2yMj5hqaM/UkHXVYcpvFXe8c9sjYkasMtuNk1aeopvszZ3H/dK886WBn/8RG
l+gG3GVyYaNLdAIneF7Y8BJdAp9GExtfokNP1C9seIkOnAa/oC7nreuzsJmZMB5mWRRqLZVq
kaBgMkdAgW6PSy2dh/6OVJmirRheBbq1W94mF6XSqqpT6qOAQfUBBbqZmPCIy1mgsz2DSVM7
Eo8t0P3sJntKRkoiaaWmImj6XUB9bo9L6TVTqpL0l9PGuz4XqeW+qT5HTUBJd2GjX/kFtGy9
oNH1udxRw64LG12fG2hz/8SGt0ii6YcTGy3oxoP63HCqz9X163ZGJoyHURa1cs+pFYaPuMml
VUsl3ara8GOTSzXfv5Qzpw4nrVWPo/C78tweldKstanXNlqDj4+dkizWJeAZmPCIi5ne6baB
TxfDMuD0BxervLvy3B4Z1XFpdC66bxAqcEXrq63y9sgUG4vqJZehKhXXp39keS5/hVUeGkYe
XGxCZYnDo9FB/n6TfZ+gTioTG13PTAmVHxc2Wv4ybMV8YUPXl8mmfsBf54UN/f5EX4AEGuRN
bOjn43ZcHd3YbLBhXSqaq6LGX2PmTIxnORNd34CcuAxVwAOtaA6HIdTbCZIdLmbGl8jmULs+
jcCjdi8Hv7TWvztc8pGbVc3I4lnQWpNe5FLRlPWU0oyZeMRFVZYxMX9lXSC0r3V3BPVvknFd
0dwj0zK3YoGBqhgbaE3h5OC3TjP53CQjrBo+i3l3dtBSaLc8+6vL338aB7+W8Gb5iY1Wdq2A
wy4TG63s+kDLKxc2VtnxkSs4GzyxscqOdM0Y9vAzbKyy68eo4Oz3xLoou6XFGqWZNmH/54m2
G7WzpCuuCmz90It8fF+W2m6TDZsHNulLqsjoA2z1t4s81F1ZHiVussmHjTrTaPp0GBk282OH
yW3Vd8uuiBebj2dsklVrKVOTQZUEDJVMTuXaupwR3qbTuJlLc6UqPMBHqV7lcWxNtJxF36Yj
IkVa4t6kJtDafLdk+5Z5v4CnX83gsOvEhneCod4qExuu7x7Iu3h1pw9bWN0ZNlbdlYMS+Pkm
NlbdjSN1NHjjwrqou+WxNSV6KYhn0RtDxZ2chikJ3bvbRS7qbjlYsslGtyFJVNXVTtVc5EB1
lz2cbE5pvHrjbrExoWZeKbWrtsug63T2sUxJeRn09mLz8YyN6jQVHN2qXbpEAhaJ7SqXkteN
utukoxu2Tp1TEYsUROWQR59E5mUX7+f+6rTeRmKzay4EB/HtNb++1d0vZPCH5kdNbLTIQ0Mh
L2isxGtHRe0RJzZW5NUjMahBJzZW5IllB4P2fhc29PMVOrKANaKJdRF5S1ddSvklJJ5FPqRS
B49qDn8FfFVlH1O8W5G3xcYcvJte0oplzqMa/PAYpNKlWbaOba8NF5YyVBZVEjRI8vAYbFKR
99M77eMZGxUEPKi02nRL0QTWeC4lr7pMWdtmYxsJIt0gZeYKFyQ9epgyL1uUP7fpiP5qVKvm
LKm0Bket/ZF9in+8098A36wTG6vr9G3Z0THiCxur7OSoXMCzrgsbur45HWmgwvjCxq6vfifw
57uw0fsKyWBA+8S6KLulYwclfqmHZ6Ec2Vww9Z3be0FjqPUil+TcZRPhj202tXAVTqT6jgUt
Rno4ClFbaqHPbTb6llX9oC9yVd3o0uy9bP8m7G7qxPzSDg8DIDJxS70zjZHAoXW7ykMKrQ3/
tukI99YLnVqI8NRZn5HipT3M/uoMzo272fbo4qB03kPFHsru20z/wBfsxEZ336UGTu1MbPTp
LI0OJ+gaNlbgkW7x0bHdCxu7vlVfu9hj5oLGfrpygCM9CnQRdjenZeUlHp5lcjA1fZpnK9pV
sD+cXM7+qCyTgH9ss6nFDHYH1STgfGSErtskI0k3fMlMPEoCzdh84lLyOWp1f6N9PGNjxbdS
2Nx7mIhwv2CXkt24KQ5v0rEmtaG6TnLvjeEuNY8pEd2G/exee04nNavcq6rrlFHVvXevvXXd
9xr/NcZ+fBc0ul5XKjjmObHR9TpB650TG12vyw1tVryw4fW6Bp50Tmx0va50NMD5wnrIuqWP
mb5t5aUdnmVAcErUzf64ow3udo1LuW45wrhNppZaW0ujlVHA/nYv7787WbfJRmWdzTCOWjIa
Zu4l6/LN1I68hMPDGIhs1tScCldmXNZ9eb1uk45w092D9E5U4PhZl3JdopvGzt3FGdnsP1lF
KhWwheFdrvu9PQAzVi65oNHFupJA0+mJjS7WsaBP5AsbXazrCR01vrDRxboOq88LG12uawn0
eJxYl6LdqsylL936khDP0iCYLeQ0l5rg6RC76KtPYzfZqBAalgRrgVJg7SGiarfJRtIYuXHr
oooIHWN2qtrdyLv6UhAPEyGE9RY7uYzW4dBWFzMUuakPb9IR6UJ5kLAMgk2RXewAqd8MU+zS
IdXc1pNhx+Xg5M6fWrbjrzAEBO1/XB5GbiMe8dZ7tYHf04WNrukQoQ3PFzZadWb4sOrChq4v
p0OfMNj3N7Gh318ZqiTBRIiJDf18rGuWwfWdWJea4k3PfXspm2exFV3MdG/UoZoA9GXQizw0
9K1ByxYb81pRKTDsLDKD9j56jUs4XF66722SyXrX9FaonnM3BfVnyQ4bAhWdNz2A7SVrHkZX
MA9JrLImWeEXFZ0edHj5u/mxTcfi1JolpNCQCntQu3jw8bLH4nObjmT96ejCcC0Fjam3q/5E
0fnPZMOX0E72iY2u7QxQhF7QaI3XUWeFiY3WeL2AJosTG/r9id5R4FbsgsYqvHZk0Dv7gnro
u3JT6+kvEfEsxKJzrn1IV4nHYEeTXeRSVbw5ydtiY5mQZdhEpcXMgiFr2cdOsNFNVXGTTSbO
UlOy4G30OediOKMC72Yn0V8S4mGQharUXEfm0pnBEwOvXsDlVMSPbTqNyshWu84sVdCpiOax
OpxvegE36QjrJp7FjMl7huW3bD0I3gLvVzDg6+AIwMRGK7uK2i9MbLi2g0ciL2ystss2loOp
kxMaq+z4yAI6qE1stLYrFfW2ubAuZ8bLUC9K46UgnkVnjERm/tFy6gV0PHSLzrhpv99iwwdV
vaIKK5XWMHVnF7mou5uxyi02Vr4rJHaUPyiDytsu8lB35WakaLz0w7OYBh6ZOkkX/UPAfguv
ALlyU77bpKOKzqyIi7SSCGxeTi7tpznRjbrbpKPvn1oTdxm6NmCvvV71tlf2UnffZcCXwED7
iY1uHeMOHsNMbKzIa4dk8Lc/sdEiT3eCoEy5sNEyTwr4sJnYWJnXbcgAPOS+sB4yb9kS9BfR
K6mBnqVo9MI9j17LINRY6HDJOr47o90jw0fSG0GUiNSGn9G6zH3Q2hVtj4zqNSveDSkt9wTm
vdlFLiJvvZ2gV0rDIzZXSnAZQqk3HuBEYYDI26VT7ZHNVEe3mBP0UNNF5J1DQPf32mM6pVHu
2QbAcj03k5jI29r7v0Xe9zrwtUSwA59hY4VdNjEEz3wYNlbYmaseKIwnNnR9aRwNdSg7obGr
azPOYHVsYqN7P7Pg87yGdem9W0980CuigZ7FZ+TKQrmxiEWsov57Lr13NxMfu2wqq56rJNYQ
BbqIeU180Kre9bnNpvTWdWmKlYfQJo/NIcu/nc2unR7pFdDwiI0FYZQ0mHuXNArodeAUn3E3
0LtLR+xGa6laPlqG55NdJnq5rivF26vTW026xyupcu6o7cx7otdD2H2XAV8F9dPERp/Olsbg
G/bCRp/OEvj1XdDQ1c26I0ZzUSY2uixbUd+AiY3Wd4NAR5CJddF36zMzeqUz0BPLfAv1aNKo
lsRUwQl+N323NmzZZVOLFGplJLKh3ljDllWp63ObTWm1ttEL9dEy6hbt4fx0a9hCr3CGR2zM
eoXPgJbemBJeGvI4bL7z4dulI1KyCJHYHVdhg2Wfwt26z3N7dYbN8eRchq4T2Njwjs74PY34
egZfrRMbXbirGTXLuLDRhTsZoJnMxEYX7jqjn+/ChpfuChpNcWGjpR2h0aoT6yLtbk7KXvEM
9DA6o9Go0iwctIJH9HbRV5fuNtlU7pWVEFFisDc8onS3yab0OqwfMpuDxi9TuXuFMzwic1bu
arVZUxJwC+EWe3tz9L9JRrjQMK+WMkYBOxl2hxD+RmftxLe9Nr00ZpJRWTq+Ou/YWwdd9011
uwx2WV/Q6KrdaOi53YWNrtrp5hQu2xk2um7XOvr9Xdjoul1PqOfNhY2+/wjtWpjYrxZ3r4wG
epbRkFsREmYeFXRmjNB2m2RqYX3bUrX2XzS0xsuI76Zst8mmtNaIzSqxonkTXmW75YjIf99o
H8/YmLtJ6l313VAJkQku23noIZX6P7vVHtMRkZqHKtVKmcEKvpMRny7Pz+6156szhugOdEjq
esPBRnx/ZNnuS4z4CH26enje/sZWfBVNG5vY6JoOnO5xQqNFZ4Yrihc2VnSaeSJ61H5hQ78/
c14p4M90YkM/H9dDn86wEZ9hPURnWb1tVAu8EiToWYJEJ5VnNj1iji2wUYtDped+yGOLjZnq
0ZDGjakUwYSNlxPfjVHLHhvzXBFLwaxUK/yscxrlvTssfgVIPGJzpntYQbEx116j0z1upjw2
6TQLO8zNSsk5gRNFTk581G+Kipt0hCwVJ6dhNtADPvt+O/F5qbtvcuIjVA1PbPTBYj1PN7CD
RcNGyzx9bcIyz7Ch68vW5wdafE1srMwjvafAzzex/+vn+y8AAAD//+xdS7LcOJI8UdOA+AIX
kFm/d4qxXs1iuhYz97eJSJLayEg5URD06SyzLvXCWUpPZiYd8XH/gTKvdTC66cDOkHntRuad
SRL1WZJEK1JJhYwMT5JocxxbbmTeEJtQbCEhWrWcwRRFHVumzGt6vWLzOciGttpDtHI8gM0I
LbTHRVM6x9eGy/XMkXjE5mW4XHM+QVysgEMhk4qLxW7q2IN0PM7mcaCgGiJPQWfOuGqKf7Td
FBcH6Wj8AlDPuWAtFY8afvvxTZJ5y/34egGtRg7s6t5d62gK2Y5dru8amhK6Y9fqO95QO75E
rtV2nEazYAlvx67Vdh7PUPD5dGCnaLurR1Q8cc/AhvosS6O7NWmt9RYCHt0pmLKdfOfGN8aG
t6okJeMnmjqYCJAXTdF2N0YtQ2zSc4WVvXEJNmDNa5ZRC91MBZ5xDY/YhEorLiUZaRy169K5
QJabY8QgHZP4UktP70dyQwPp5rjxXebrfY7fHZW4xGshtYrv8w7ReWu7X8WNr2bZAZZ4iV0r
8Xwr4ENph64VeL6pPPDik/VefAUO09ixq0VeHPSx13dg14q8nIdFC3g7dorIu+menaEN9WGg
BoUc4las1SLoesGcQI27At4QmzTWq1SlCWmqiaVufJe+IJ+DbGir3snFpXLa8qEFvCnTgTeW
y/WMbHjEJn31KkkPveXUwbCTaWZ8N8eJQTah7TKbL7478eSDJeskM77vftQe04m7kunWvVCt
4E7A24vv9/Tiy20ydKU3sWtlHW2tggZVB3atsNPNCIz5OrBL72/tm1IFX9+OXd15j6M+6Iay
Y1ePf1YDhd2BnSHs7txazryG+ixLI561Ie1ywivkA7z2MUMK3bq1DLIxcQqVWlIOoV6Tk9xa
+KaiMshGWpwIyJ2IK+gHMs2t5aZ6d6Y1PGKT1bueCwVpbVIdHO2e5sb33Y/aYzrK3V9GlrW+
ZPA6M77bpd7Rm5OJ2PW12lsa+DvwNuP7rc34agHtZA/s6taso6/vwK5uzdYGthcP7NL7SyX+
TrDh84Iur8pW9O7u2NXyrlWC5V1ip9Ttrseh6ExqoGcZGhRCqGVqQtcKrlpOk3fX1ZRRNrkz
qk3Sf8LQudfN5uxXXCcbjLIRr7leUby6wtJ7rJjyTfvv+iBBZ07DIzYp1LqJ5AZs6wLenGn7
FVdfnI9hOmlwFNLbTay+UjpWbvVeHyWG706Xrl3EOr/qgm95t0reLfficzSd6sCuLtx1wb34
Eru6cKdoetuBXV24g22MD+zywh2hhbEdu7xwBxcWd+wUZXcdPE9nVAM9jdEo6ZHGtViBoxom
2SzfPG4H2ZgW7ynutBbYmHhO4e7Gi2+UjTTpVIpkRQU85kwr3F0PeNIZ1PCITSq7/Bpk8ESc
IeCm349O0Rhlo9xa0TwPqaNGRwsKd8M3J510Qndbz39g2f1245ug7H6WGx85nKKR2NUCQF6F
DEwAJHZ14Y4LaDTxgq4u28VDEPRa2LHLC3cKjsUf2NVl44K6LR7YGfLOr7tldCY10MMUjaah
IJo2Y4I3ZmlCGTfk3VX54WOYjWkXb9Zca6+w1fIMsXpbuBtkI3FsMbPuzATOdE0r3N2UiM+c
hkdscvdVtPTerGSmLzy3P2XF9K5wN0hHrRZpytZJCbYn/uF2fMN3p3tT7a1aM2voksifacdH
v70d3yOhAoqUCT+SE9TwzzIJFNCy4MCuLnYWAf1FDuxyLVxB7+IDu7bYWWRzBx3zT/DSd1DT
AhnUmwd26euTssWDAzwt7tgZevgy1T5UyhlvQU9SByyzvtI0omsj8P22Kc3F2yXjMTJZVubK
aiKVBazZ5EVTxhSvl4zH2NAmRrk0belzhw5NxEUz5DDfHLzOeItHbGpIJ+Fm0iqXDgc6j+mt
b/xjbg5eQ2zSCcaqGnsPRSwNHVOc8RwiujxHfg7TUTdPRUzi6FpnXPQuds6Sdz/JJbCg8W0H
drXKcwcrsgd2tcpr4CjgDl2s8XxjQzvuB3itxuNNvMFOMoldq/FkyzgFTOPt2B+t8c6YC3oS
PRAHDPUSikhK/AHW6OOiKS3tO5E3xCaXfkJFeElTPdSsJC6aMqyoN33GITa0WXZLmYvmKDho
qDClghty/zrrhs6Qi0dsQq8xp0d3Cz3c4HGDKYlsha9NAsfYhFwLgaetdMmJENjaeoYXAnG7
TrsZpWNSS+2dmlAt4EJ7GQzveau8X8Ak0AXscB3Y5RNjiq4a79jV8q4TbgKd2LUCr5atwyY3
B3itwLN4VnescHFgVwu8OO2i+s6n5EnUS7+zeOieeRL0xOPfNlUTfZ3cawPfbpvSmKvi1wEM
Y2x449rp5c4b/3TUBHrGb1dolmsT6DE2lM/cXqV6/NvQNMMpeXkhiK4a9F8/aV+esal5kKAu
qtn9BysHdcpBgqpdbxqPsQll0zy0atwWD1qOyjub4tB9uaP/OUxHxTqV+KX3ph3sjmXK3lve
TZJ3P8UnkLaioEo5sKtVXnwaYZWX2LUqzzeDJxV27GKVx5urgTL0AK9VeX0jtIr3gq59demP
AQfOyQy7pXuNd4ZJ0BODf9tEmxNnbGxp4K6ATekFVrkcwvwYZBNyzeKp24jMRcDt6TlG56Hx
brZShtjQ1oxK6SLZQwOHKvKiKRrvSkZ8/aR9ecYm5Fozbq26U9wgdKR0ik9gLd/9pD1kkzkf
9JoHMK5FO9rZnBLnRnfV4kE6VoVzIsCLCcE5Hza0M/TWeD/XKFDBdsAOXavq4htf0QC3HbtW
1f3iNoHctnz8of7FiV17f21DM5526NpXJ1st4K72gZ2h6tqNqjtjJOhZjITEneU4rscDtxEa
IzHmHvHERWaITe6VtOKiEofMii+jzFF1N8sog2xUSKjV3oQZHZWds8563cr8+kn78oxN2VrG
oMRNz9IQg6vTcdWU0OEbP8pROireSrEcAAi5CrvIzLB/Zr0p3Y3SKelnXaRzYQb75pnt+5Z1
f1/W/aRl47jR4GjRjl09elcUPcru2NW92fhZAfXdjl2r7/qWO4yYvtuxa++vb/EzA46U79i1
ry80ueJuN4mdUre76ZidGRL0LENCtKpYCynRC1i3o8Hspm8U3hWbj0E2IdaahoBQUeMODhDV
KQ2zUHg381CDbDQ0t7B2NkND3Org0Ps3Cu/GJ/CMkHjEJrWa167dqJEV2CdwRuGA6M64aJCO
WmvcuZK0SnCIm85YBqfLOuTnOB2WWtkok2TQ6PZ3QO/vaRTYDIzOOrDLS3cdNQrcsatLd+rg
+3dg195f3oTBhvaBXXt/47iAKvcXdHVhsRbUh2fHThF2N5PuZ4YEPTH2p81bKCFu3rh1QQe7
fErp7tLO+mOQTd1aKWmpxzXNAuEYugnLmdVvElNH2Zhrq3Eo8Foc7QKEtp0i7G58ZM4IiUds
ytbj9BofMe6dWWCnkj7DJ5Duev+DdOIEkcchrsFIOuwjM2fq7qYjO0pHNGTda1M7LoXpvKfu
Jgi7n1S64wI6tR3Y1aU7QY3aXtDVhTtmvHCX2LV3t2/xGATV3Y5d+v5xRj2DAZEHdu3rK1sF
p2x26Ax1d9mQ+WflM0KCn9j681aoE8XvueZaD/h2b2VKLG+77paNsalbVyImzh1gRbN14qIp
6u7aFmWUTYu3qJfWOFQRw1p1Ruuv8PVuNp8BEg/ZFBIxftnvvGIIITYzfrWJ5focMcambGYl
Pmk900rcwC9OmbPOzHQ9AzBMh7TErwB7s05wGJ39kVU7/hEmgeDpbMZ41m9sxpezuKgZX2LX
Ck7eKpgnvkOXd4odFEwHdundrYU3qqCT3Ale+g5q2Qq6TnZg10pO3wo4SrFDpxQUb4TAmW3B
TwIH4qwjxBZ6MyvGGJ28ZobitOsizxiZkMKevVUXrfAoYFw0Y/nGy40MGGJD8augTqHOGlsF
HWfiojn1xOuhUz6TLR6xScPszum0Td4dbuJPCVHhS/38McimbLmJXFx7aPPC4L74pAUPtuty
4igdfcUEqzmxgseBd5v49zfiqwbO5B7YtQpPtngkweEPiV2t8RqD2ygHdrHGk3gagKfhE7xa
42kDzxgHdq3Ga5sbWNU+sFMKi1exA/HwPSMu+EnsgG21S9Xeu1AHmwh5zY9WeUNkQrCVEHgS
itUIlKx5zQyRV69n8MfI0MYl253Zw1NBE77joh8t8s54i0dsUq/lqmjIVWPQCLtOWSy6XeId
I5NqrbSca4zrHDWUmqTxar3ReIN0VIndUw3X4hUebXy3jCeJvOU+fEqg9dOBXa3urKLLnjt2
ubozOLTlhV2s7trWO9i52bFrtR1vjk5BHdjV2q518PUd2CkVvJtn7pnXwA+jNEyoiobSMrRp
PMuj5cZmeYwNb7X1fOSq9lB5aAt8ilR9JdNcPXOH2KRQsxY6i6QVgTetecYM3Z0PH59xDY/Y
1JyLKdSaxVG2gseIOqVYfN80HmJTMsTQ9LU8Hl9ukM6kpjGVazugUTriXikddEr8Hzj2752l
MUvd/SwbPrAJtUPXSryMbELdR3fsWonnIXvR+tiOXSvxas6qgVEQJ3ityJNNCpiVcmCXvj6p
W7wv4NTsjp1SwLs20uAzr4GfZWnEL7u3UHqVnRk7u9uk/GC76Z4NseFcsCml5QQaVzCiNi6a
IIuq081k4BCb0Gtp5qvpQCOvfWFM5M2ZDLwReWdcwyM2qdeYxJo5UQdr35NEHunNcWKITcq1
zHQm59K7wbJoisir/Xp3fJSOllq5ZrWzecfXPv7I+OA/3YgvfkswbXJg12q7dBEDB9wO7Fpt
p1v8KONWfIFden+54a/vwK69v/GeMNp837Grxz/jrwTPFjt2irK72hqN5+0Z1cDPohrEyShn
/NNcDLXxlRn2dXK5l/gxyKZm8ETGPXE2ANGkhimVVb/rmA2SkZ5Zb5nj3Qg9hk3Kjr3x4uMz
qOERm7K10rrU1gr16uC2dTr4TZnAuxpp+Bimo+yl5DiDeXUwXrDMcUrkdjPsOUgn1+Bb7Wyl
i4OWTWWwd/5Wdr+AF5/nxBps2JLY1f1Z8CfvhVzdm60NPZvu2LXiLgMnQDeUA7u6MKu9wnYo
iV392SNwYXSHTpF21xYafCY08LOEBiHv8eHz9M0Haw9x0ZR13jtpN8QmZdory1ea5lbiWm13
JR8+h9lIb6WwM3V1RRdgf7y2OwMaHrFJldZ6L6EbOIfWUPUwxWe59puq3SCdOAux9RKsahew
3D3JZ/nab/1znE7RrD+KtEyggaXq22f572u79S58BB7iD+zqqp0RaBB8YFdX7RSsau/Q1bLO
DZMlO3S1qKuKev3u2NUVu+YFfH07doasa9eWt3xGNPCz+AzV4uk30cgMdAKhKQ+nGtrr+lk7
xCZd65zTEq14eqMtdK2rLtcefKNslGuounhAt4IOxw7uMX6j6r77QfvyjEy6JGfUce+5EmTg
rOokb+W79IxROirxWfOWC+fFYUfBKaqOys0JYpCOhOJu8QMQ0k6N3r3YlaruJ1nwEbjuuUNX
10w6g6NOB3Z1zY7hxNsdu/bu1q0XsKxxYNfeX49fQrQhu2NXN4wzVgxtGCd2StXuZp/izGfg
Z9kZas0yJLZ6I3ABiKYkANxmZ4yxSaXWM+utv/QdOs41Jzvjcmb/c5hNfKrFjJpUEVzfzcm8
vdF3ZzrDIzah1Kxx9v3ZzRTeQGhTwib85iQxSCeNr6W+dswLGjM5KzvjzvBxlA61OD1Wa8Ja
8H3ZP9IU5Ye48MFyYMrszrRNj/U+fBV0aTmwq8s65g0exErsat1JjrarduzS+1sLbZ3ASc8T
vPQd1FwsAaNbDuzS18e2aUPrsjt2SmHxZvT+DJDgJ6b+cegh5e5W1K2CZfA0K5+hPO9sWobY
pK+eSCnaSkUz/2Z58cnNduUQGdookzDyzlRygb345ux43BxxzvSIR2zSi8+y8c1G1GEv6yle
fLc+LUNsyuuZ10vN/7GDcyOTfFro8vz5OUxHKW5Pj8MgaxMwbzyv+hN153+UGR9aXTywq8s7
2kGVcmBXy7yGhmm+oItFXjqcgM3PE7xW5NWNHXsS7NC1Es83R40CD+yU4uJ1yUfOFAl5Yu1v
W41f9ZKblQJH2eZFP1jijbEJuaZWrXAvZA4WF+OiGdYzdxpvjE1qPHen4BJKAnRVWKDx5AyR
eMTm5bfs3kN8VBGwbzDLb/ky0PpjkE2otTgbqZeaUq/DI3Q+oxV+vbzyOUxHM8LRVULnKdg0
Gd1deUu8X8GKD83mPbCrW8cZa4S2jhO7XNsp6AV2YBeru5bj5LAVnywu0SpvCru07NjV6i4n
aVB1l9gZ6u4mTEPOxAZ5FqaRU+vxs67UMxUAteKbk6ZxPYU/xoa37OBmpzUeUQVMYuE5WvVW
3Q2xSXUXotszIKQYGHEwS93pdalYzsCGR2zSiq+E8tYiyQZdTZ5RKqbiV1ObH4Ns0opPe9Me
X5zi+C7vFJeWUq87x6N0xMRzRrg3KQb+8JbBJcq3vPuFvPgInHo4sKsHyOK4Dh5rd+xaledb
OmjBbnwyo0L2SOX1LGuCKu+FXavyJO4ZGqaxY9eqvB7CFxxyOrBTanjXy5ZyRjbIszCN7AW6
Vk93EHDL26Yoifsa3hCbbLlWq05dOhewAbGgTzvGJgVbbbWZNuMu4FTKrBrejco7IxsesUnB
ZlRTgHc8vnyS4XK9OU8MsXkZLpcSCi9Uq3df68XXblTeIB1pVdOPz3rt6IP17bj8O3rxta2i
I3gHdq2yoy29VNGt3sSuVXYvfziwPrZjl97f9NdDJ/AO7Oreu6P9qBd09QAouvK+Q6eoumsf
PjmjGuRZVIN4yQftyyHNUBffST5817uWY2zSdyUkUC2izg2cIYqLZmhUv1QOn8NspOUWi5rk
Lgu69jElV+zOrEXOpIZHbNKIj9xVnYyZC7pY0GZ4z9DN+N0oHeU4D9UUQ521wXuwU1qzdFXD
/xymE2QaS+nOvSnYtXvLut/YiC8Um4Hq5MCu7s56AZf/D+zq7mwIXjgoLbFr1V3fcqYHNuML
7Oq6bEW9+F7Q1equN1R87tgp+u7KOj+eumdKgzxLaRAqlSgeuqYKpzTMMGYMfXdTSxlik64t
7JSyqBUFg8Xyohn6jq5jDUbZSLDIpdFm7DCbKbNqt/ruDGl4xCbN+DjkqqpZj7MEWueaZLR8
Vef6GKajRi09gkS7GuxMPGXp+s62ZZSOdO/USvCJjzI4Mv62bfk9zfhyDx0140vs6rJdfKFA
YbdjV5fttKExjzt2ubADq547dO3dta0YOLR4YFcLO1Q47NAZss6uCl3xsD0zGuRZfIZWzxIX
19pQ96PBXbknqm6ITAo0ivOldRGzuljV3VRSBtloCSLduucYFLqBMOZ6+42qu6kPnwENj9ik
WTIZxY9cb+TesCLkJIvlOzO+UToqxhpnh9Cp1RyWQXPM+K59H0fpSOfaNF10akV7Ye/4jN/a
jI/R0coDu7pnFx9D8IG0Y1dX7ZjA/LYDu/b+5rgImty6Y1dX7UjBquKBXV41hut2O3aGwLs0
z4/n7hnUIA9DNNLawcR6nNgJDtGYknx7p/CG2IRYC3HH3fKd6oyxmabwbvqyg2xy2K6zkVBI
CNiOb4okurHjkzOm4RGb0GpSxKhyZasuqCSaEcxILFdF1Y9hOmosSqVXLaWA35xJdTu+3BH5
HKdTSYrWUrq74u6Cv2WIxjr99j9//fuv//vr3//9r3/EO1vKP/7rf/+19DmFPeFXayNQFk34
VZ4gwH+GK6H0rSmYM3RgV1e30EGhHbpafIvg+XWJXXp3tW4OvrwduvTd4xxyQB3lduzS19dl
Q5O7d+gU4X3TMD+jNORJvgFvVaRlfSgfu+BAZF40Q3hfHiM+BtnQVmu2l51ac9RbMS+aIbz1
prQ6xEY3l2rqJrlfqti9yYtmCO+70YwzSeMRm7oVtu7mtRVTcAUpLprBhi5XkD4G2ZTNeloi
1UbdDJQSJX6lptSJr3OJR+9N60zxYQtKqKV3XvM7iu5fq6z6E70INccdwJt9YFfXVltFk8R2
7Fp551s8a8DG+Y5de39pI9TL8cCuvb9tS9sR7P7u2LVn1hafeXDi9cBOmYm8aZ6fcRryJOIg
rfhKiLwMf6topO8k/767qJMxNhl14h5KojtzBUXRrKiTGxvgMTa6Ve/M3JisKbj7GxdNmYm8
k3hnmMbDe1NYtZkGl/ivoymDcyTeTdLJGJs96SS3fimzTjpcWp2RdFLv3AgHb44r6WuLuRQF
rZHyorfImyPy1u5DeBw2GriufmBXqzsjfN01sauLdy6oGcOOXavufGutgj4wO3Zt+c42cVDd
HdjV5bvewfLigZ2h7vqNujszK+RZAIekO7MxF8rkClDdzRiTjefPTVlliA2FHvL0ztYq8exF
3ZlnfLZD3d10zofY6GvSkxoFFTH0yzplDuB+4+WMrHjEJndXPOcaSmeXDi5XTZqNrO1mNnKQ
jlal+Na0LEs6OLk6msABuwh9DtJJQ6DarVlQaWixeNRF6C3vfhE3Qo87WMDljQO7VuVZppuD
P+M7dnUNTwScz3pB12q8tlkFp5wP7FqNR5ui05sHdq3G462g6ZMHdorGuzq6/7PqmVmhzxI4
WHs3tWIhIBvapJ0y6ymXAXgfg2zq1kx7ziFRHDrBkIc6JQ83NN71c3eMjW7MoVklg7yogGx0
kkfzzf6LnpEVj9ikWqu9C1Fu8wjDrjVTRFG9+uJ8DNOJw5G0EHkhpgg8zY9aNH9TXv3uR+0h
m3x+CzcxZXWC7Z74vdP8tyXeaivCzN7C7u8OXSvqaHMFB8cO7FpRp5t3sPR0YJfeXS6bCdg4
PrBr7288bCvqqrtjl74+Iby0fWBnyDq6XnrRM6xCn8U7dClNuTUSuFk2ZY5QLucIP4a5cHwO
WCU+rSGE4PLDnMLdtVXNGJv40JQeRERI+eVOApUhZ8QlUrnZntczqeIRm7K5FOemnYTKa0EI
G1ab0pfVa6uaUTpKnnFt8cVWoQ4X7qZI7u9/1h7Syaa5lE4hudkbbAdQhti8Vd0v4ERIW5x9
waWKHbu6Mwt3Xl7Q1X1ZVjQ/ZMeuFXd1o8ZgSOqOXfv+9Q1c6Hkh1wq7+FkDi9k7dEq17rpP
pmc6hT7Lc+g1FFBzTZsXcGwoL5oh7C77yx/DbKjmRnb3SlwKWnSgKSsVl1Loc5BNGglRqFTJ
R20FpQNNcquxm7rwGU7xiE1KtDRlLhkS1xV2uZsi7OpdYXiQjoSucxNlVdeGDtzNcGeneuNB
OEqneyvcsmgX3x7wFBFXvT2m/76yW+xBmB4J4ATBgV1dsWvgU3+HLq/XwXuyO3Z1vS5OsXC9
LrGr63XewUWeA7u6XtfQdsWBnSLsbppjZ0CFPguoiHeuslr8rDs59nueF00Rdje9sUE23EQ6
U2nx2FV0HnxOxe5SCn0OsqHNs+PWijRhA11d8qIpwu7mCHHGUzxiExKNmkuuURhZB3+646oZ
JS663HL5GKajGcvcOP4VZ4iKFiDnjNrdVeyG6GTxLZO4iUUcnXF+V+x+YxdC2uK8CFfsEru6
YicdbCge2NU1O0WtPA7s6podms2xQ1dX7LyDuYQHdq28K1tTcK30wE6Rd1d9pXjonvkU+iyf
ojWtLTNynTvYJRt1QfhG3l1JiI9hNrX3OCqZ5r6foGxogkFF9UtB9DnIJiP4NG5KxhdzNdgf
csqerN0cJM50ikdsUqjlwKC23ApR2JZ5iryr7eYkMUgnxVAVod47GWM/VSvqdoN0unHvtWTq
ThEwuiGv+hP1HcP67sEjA3xPZyRh/M7We2AbcYeuVZyyFQJHsA7s8i6xo82qHbv27nLoIOxn
f4cuffcsNDhonrZDl7665lspoOf6gZ2iN6/8JUIFnMkZ+izUxDw7xTW+HV5Bo5m4aAYbuSyO
fgyyiS+5edDooTd7Y+zTExdN2eq4VGifg2x04yqNQjeXJgKuOOVFM/Tmjee1nrkZj9jEoauV
yk4WH+MQ56iimVEmuFl1/RikUzdmy653tr3RkMfRVdcHviyjbFwsnbutGcPzFW9blmmy7id5
7wnopL9D16o72zq+tNtX7+zGXwnmj+/QtXeW0usX3NndsWurdekeBhY7D+zau1t40wYm6p3g
GfruxndPz9wMfZJlwFuJl9bYPQSRgLNmcdGceuLN1P0QmxCeViz0qpXOBH7/8qIp+u6Kzecg
G9tSPnj6EMeN75iEyIt+aEPy6yftyzM22Vt09RZqtRT0yz3Jd6/cRBGPsQndmRX40I2hikgd
Tlae8MWhV235/qP2kA5tRUM1es8PHINthbzoLfDmCLz1vnuou/mBXd0r7uhPxIFdre5aAR+W
B3atvvO4Z+DrO7BL3z/3jQs4q3BgF+u7slUCK9sneEr97kbfnfEM+iw6Q9jiedFLryKghoiL
pizwXlYjPwbZyKa9V6+tUTFRcAtnszn94puH7hAbfeWoK0ltIVlBhycdbOE9cN7TM57hEZt0
3jOuvXHrXQvoDDHLlaXdlIqH6ITy7FmKdC3NCR38nnIwiptzU78bZCNxhFBLfdc6aM4UFw3d
m7e++3WM9wh9ih3YtTLPN+oNlHk7dq0MSDc9cMv4wK6VeW3TBv7QHtjVZTxHZfKBXSzzeibG
gDf4AE+ReTdLlmdEgz6Lz2B1ZUr3wtYFLePNMd/rN6P4Q2xos9qlN5FKpLCzyYx9tZB51/EZ
Y2xso7g1JuKNDN1wi4vm9DVvxgLPhIZHbFKwkfaqNUNwCd5/nSLzXi6t9x+1x3RM0hkxbR5D
54EPo7xqxt2hm62PITp1U3ZRa90yjQ+OwX4bLP/9rY/l7nui6Al4x67VdvlIQkt4O3bts183
62h0xo5den/TaLqi+7I7dun7x5yef5h0OrBrX1/fWgNtlQ/sFGV34793xjPoM8t8L62YceHu
DA481ikub/U1/XH1uB1iQ1v677n36mxU4ezbGeVIt+vojFE2KsUpPttxaxy0VabBp+03Cx83
q0VnOMMjNilqzHMVh3N/HLRHjKsm+M3f1CM/hum0Ws3jCFE4VDccnTFjFOd+4WOQTjcqqj1E
arACFyn/1IWP/xALPmJwSOvArh7AK4Z68O3Y1U1auMl4YJfe3zTWK2gwxY5dXZ0tsALdsWur
i7aB+7wBnKLtrltmdsYy2DOv/J5DNyGIenrXoaf1OSZ8ft0xG2VjasxmtbYSz12QzaThu+sc
gzE2tDXReESrdPMOm/C1KWLostX89ZP25RmbXMttHnpeVKwzOLk6yYSvXJZUP4bpGHd1DZ1a
PI5uS6t29XKY8HOQTraNm5FSz4wWcGOxDg56vqXdz/Xgiy8hXrXrq6PQeBN3uGqX2OVVO7C7
tUNX1+wyrhFVxIldXrMz1ENmx66u2XVFa4o7doquu15ltDOZwZ655VvXSk1Lqb2CzhlZ6JtS
s7veZBxjQ1vVeI9U4llbumEZIHnRFF133SEbZaPBxF/7zERgokle9EOF0NdP2pdnbFIItdCo
oejiv+54zW7OVsV1zW6UTqu1akghifcKdDNdULIbZdONemnN43vj6ALPu2T3e3vwoQNjB3at
vNOte8cOfwd2dclO4ILdjBn1ZwbLHV04PrCry3VSwGHPA7t6GLAr2JA9sFPE3XWbzM50BnuW
NZEOfMyt9hB5qGHkLAe+60i0UTZm1qxy5ZZ/okW7OY4oN0/cITa0edyTRtKq559o0W7Kxuxl
e/nrJ+3LMzZZtKsZziDEhSvYX57kwHfdX/4YpmPiJZS3mFftYOdjVn/5ckHkc5BOzc35kj7w
bqWCowyjCyK/urj7IQZ8aCr6nET0aase6y340FXeA7t8DrCA++Qv6PIesYL12AO7VnRKPNHA
ILkDu/T9s74pg+f0A7v29cV7AroZ7NApkvOqAhdC4MyNsGe5EZWscVMnIUFNj7Y6QQdULddh
bWNsZKN4bpqW+LJLB8u9edEMyenXYW1jbDiXeLsWCg1AaAGOJy3xXna9v37SvjxjU3LQuWVu
LTuXAvYyypTSNcUH4nsftYd0alpXOXE3agXdF8+LZrDxm9L1IJvcgGxdtHd7GTBibN5t4lnK
7ie58Cla1zmwawWebB0dYzuwqyVeJ/CH7MCuFfC8tYqaaO/Ype+fl6052DQ+sEtfX8scV7Dm
fmCniLxrfzQ70yPsWXqEtmZp8p3+xA214Jrhul31svf1MchGttqyesVZjXPGSldx0Qw27jd1
xUE23oOOdw/ZimYsTSor3hgt2xkd8YhMfEfNlTMdTKoIvsE7Iwnj2trkY5BOzVYGh/r2kOHo
xmFeNGUU8KaqOMjGSgvtmGk4RcAMmbhoqAP+1ni/gBFfnE8w8XRgV4s7d9Ag48CuFncNzTQ+
sKsHAipqHnVg14q7tmll0Ahyx66u31ED+3gHdoKAoMuaVzxzz6gGexajoSUD2yStJpqhya86
ZyLw2oZvjI1sZi1DtDpJ2sWiNnxTmsZ+Hds2xobT0aR3qlVc0FRenuRbdznf+PWT9uUZmxIn
ArdWiLtrCAlU3c3wSLxZjfgYpJNJllK6x+2RB4YmdU7Gyc2ix+DN6ZVIapyKjA1ckSqDC19v
dffr2PAp+it5YNeKPNtUQRFwYNeKPN/EwK7XgV1boaVNwKHKHbpWQvkWDzdQQu3YtXe3hM5x
8AWe4BkVvJssDTvzGuxhlkYxUo7XJ8pgmSgumrHOq+VmFn+QTevcKnnphUEPPp4z5uiXu8mf
g2R0ay5VW1UKjQc6Zk6qeN0k89oZ1vCITE74sXDp0ksVAYurk+YC+fsftMd0gkg352K1txB7
qCqa4ztzUyseolM3Ya7xpYmDXkWHNfKit8b720sf6y34BAzDO7BrdR1tJuCq/4Fd++TXzQg0
uDmwS+9vvieg4doOXfruMW+Ohn4e2LWvj0IOgSM3B3ZK6e7aWtnOlAZ7aJ2v9EoC8NYMHMLP
i6aouhuTliE2uZfbJXcrieUVF4yNEk4xafGbesogmyK5HWHc49ergkMog7FV38x33ZwfzpCG
R2zKpuKq0ipzV31Fb/8/AAAA///sfcuSJDmO5BcNhQBIgPyBENmIz5jdwx52+rD7/7KAGy0P
U2JWaiwGM6rLu1sq+6DMcjjNjUo8VBEitGY2+W6YdzKc4D9O7HJVv5PDmjNLpnmvw/maDseM
hV81ZnKuCrdGTl0i3sTuRwjwZXRg8QXdXZplQ195B3Z3aZZRD7KB3cvuzI9CUAB6YPfypxqV
HIw+vaB7P12LTjpQSubALmF3NxJ8pzmDPhPM9/OJrfWWK1W832ZFKbPmm2rZVDRO1FoXZ0K5
s+SC9hCu6brjG3Y3GY3UyAn16ntEoDBALFrC7m7uEac1w6NoXvLKZBK1zOo/B2xzlskrXyt5
z4bTivbGXcWkgbf4vEgf8a4wOxlNz12s+LsgxDgFkwV6V2b/phJ8DeRNA7s7a2do8Whgt2ft
0Gn3F3R7zg4dWxvY7Vk7ARsqB3Z71s5AcfmBXVGL5Rted1oz6DPbjFJalsxOIfpLy+KHZO2m
ookEXEhNlK69ogPNy7J21763s9HkWlorYloyod3Fq7J2f/qkfTyLJrJ2pRfWTCKCXtnyIheQ
u6zdZDiNhHoWlRxk6Mck7SajMRNhZtMw4QOlON9Ju7+1BB/cLDawu9N21hRO2wV2d9quoImd
gd2dtmsFleM/sHsJVEmKShi/oFs/XQmpBgIHGA/sCnp3o7BspzuDPfSa6EqiLNlqYZTerVFY
btd2BnPROFMjrqzWrfUK+4ituFo5vbv2u52NpvitoOeqFq37qMfbCmUgp3fXzXZ2ejM8iiYS
cLWpb0yOeUywTTovsTW5pXez4TTSFinI3HpXOJw19r2X6fuv6XB6bbVotlKjURUN599TYpm/
Q4UPHFzYPLOA9lWuuAEv4MK/SRnQ31qoMKCt6Nx+6DTCaE3nwG7nwQ3MTQzs1t0l/1LgCuwJ
3s2EW8O1CwO79fN186cKbOMZ2CUl7BuGcjpa2BObAf9oVo3EmuRot8LmzJbwrXsuPBVN0Fql
7mw4l4paQMTk/BIufO0QPBdNTZ1yqzGlISUzxuzrEoc/58JXVdJfT9rH070p5i86/5qEM8Oe
eGXFGA23a3HAuWjiehutieKMuGdUo2iV1uHdtWsqHAohSvNYqBV+YCb5b8mE/1HqgGA28YDu
JXk1tYxayB7YvSTPUu6oNuCB3UzyShJ49HmA9+5wT1TQHT6we0leZGLALs+BXULybo7e09nC
nrgNWIrB1eoEL4y+QL33WLSknn0tIDMXTWRii5++Jv5P1FRnUfrWLudxvyajqUmyqNXWqnID
3TPrpC7vH3jEtVWwnb4Wj6JxvlY791KolpLBIZQopK0geTem1HPR+Jln6nSIVfxB44Y29q0Y
RuPcroeL58Lx34DvjXWrOceMEPrD+bc0HflHyAMqgSmUgd3N71RwfhfY3Uk8q2AOYWD38jux
0KwDz78B3pvE06SoAN/A7t3hHJ1UYLvsCV7C8G7O3dNIwp6o+7dEXcIGPueuHZw7a2tmN+4m
UeaieU2iGHHoJjPqVbBqEkWvOxbnotGUM5H2RiWzgFWLWPStmaJfT9rHs2goObsTija/ag20
pY1FC6J5mfLdP2kPo/GfNIUTuJQe8/lwRXvFVf5WPmZ2cwr7a6BVKayo/EQsejO8RQzvN0kE
shh4qz+we4meplYKSPQO7O5EXhG0y//Abid6fnKATHSA9xI9TrC78Qu6N43Xkilo8jGwS0je
zdF7GknYE3l/S6220smPXyOD03grSL+TvJta7VQ0YYVsZqX3mH8AlZMXWSG/tICvTt6paPx+
qqWqmLOIzODLpC5q9LsjeaeRxMO96c5UrbbsjxuD+o2xaEWfH//pk/YwmpyKX4xqF6Xut7iM
pvGWZCWvfem+pjdHmpZGMT3dC5jgmfWle5O836wRCNrfHtC9tI6TNbDBc2D30roaGlLgz+PA
7q2+l9RBDbUDund343xGJ8kP7NbPVyS6o2Dnu8AuIXU3wyingYQ9M5AoZpW1kR9NBpp7yKoG
vCsDic/JaOJsKrllEXKmWtAS04rrCpnepFOmovGXlmntMZxr/gc6jLLC5ptf6pf3T9rH473h
RtWy+b5nsNLsi1YIP3O9yRFPRRM5uFDUDMWiLA1MefuqFeG8Ktv3j9rjzcnRsyr11aeBeg3P
aQK/Od2PkAckUKz8gO4uzWY0wTCwu0uzgo6fDexealeToe3nA7v3++upC3oCHNi95I6csIEZ
u4FdQu5ujtzTOcKe2WD4pay9FGx7FrCD3xetMfW4Vm2biyb8j5s0o0rdCCZ3SwxXzK725msy
Gk5V/YzumZWECLZMXpIUuiN3p3HEw70RLtz9SWuKXttizZKq7E3f3VQw4VUqoTNu3W8RneCE
3YpZEboUgf+aDscv7zUzlR7jFWjD6lwDwJvc/WZ5wIImJQ7s7pRdBxPGB3R3ws7v8CArObDb
E3aoZcvAbk/ZCWjqMbDbU3ZVQP2YA/vdKbvTOMKeiPlH9q02ElbuBZ0A8kUrKpelX51On5PR
RPat5m711Z9WsLN2tpz0JGU3FU1k35rl1hvV0hWLhid73J+wutM24unecLWWueWOllp2ZOym
gomMXXgLF9PGnBmepvj2jN3k3mTNzreLf1OVwOTwO2X3txYHRLt3D+julF3cmNCUXWB3p+xK
w1N2gd2dsutg3v2Abk/YKSg3MrC7E3bcQeo+sN+dsDtdI+yJlL84rwlvsxChywImhWQNGSr9
RqRiKppI2BGb+tPQtMDt4LxGGvDmwJ2KhlPNpTc1KyYCStXEou+mdqdpxMO9EQ4BkdYti4BD
UssydlfRfE5GE7k3qixGHhMR+CLdkbGbDMfvQyTa40GjDF6KfNXUqfDTyZ18hzIgSFVWsJS/
sQZfA0foD+hewimpdzDZ9IJurxCjxkIDu3VvO4VpHfb1DezW7081KYNazwO79fM1f+DR29jA
LiGcV6TGacBpZ2FPPAZqqtpbZT+fYggCTC6nukKapfSbwt1UNCVl1ewcrfqxiY6k+aIV0dil
xtvX9N6Uxq1W355StGH0ua7Sor7JWp9uFo+ieSX8pZrmViImdN5mSfZNbgjnZDTBzLpm4864
9eKKisK9Msvs3mQybTG6W2D1vfYuEK/idb9Jfa8w6HE/sHsJnqYOTp8c0N0Erxs4VDywW3eX
mJz0gkfgCd6bs6uJFUw8DOzeHc4WknrgFg/wCpJHV0Tif1A7TS3aE6MBS9TslRzx/zKYJrVV
6izXR+9cNOxfdEj1aHOSUkDlW17jemw3R+9cNH73K9x75EmNCHQ91kVE4kZ/r52WFg/3plCX
4rtTS+aG5khXvBtvjHU/J6PJqXXflR414+a3FYyBhx3vkqzi9X1idnNIKmkoNFHTgo4Tzd2s
3zTvB+jvFbBn44Durhd30NHwgO5md9bAbMjA7mV3h5zeE+m9rd+fWRK0G2BgN3O7kjKYURnY
Jczuij34eXtaNLQnuvktUcjFqHb/Cq1iAfmiJdO7/VpZeS6akjRb79WvmiYdFL72RUvqxZfa
bl+T0agT6B4nrr8dOIMDopr4u3X32unQ8CiakNDrLytacd6NNtKkFaoBTHfMbjKa3CMNGc2A
TrrR6jct2Ru5ds+YjaaY+a+/9uzEDnzSaDJR/CZ2P0h2L4M9WQO7l+GFgj867XFg93IA88sq
mOt+QTczvJIaKgp4YHdn7wweNTqwe3eXJBJy2Pd3YJcwvCsW4efu6c/QnnlnmF/NxPmdNOkd
6wSKRUtyd9f6LHPRcFJWP9xCQTAL2r6RdEER0GnYtXfGXDQaEwWRqOGiIXoLMrw1AwWXA8m/
nrSPZ9GEtqE/YSxmWRvvFERkoWvRvbloctLC4k9bzL1rAetcsWoJYf3TR+3x5tSu4rSeo2MT
dAIhv0+9Kd5fnvbYLronFZ3zOLC7++6kgDWkgd178Nekht7oDuze/ZXkryR4CjWwW78/cS6E
DmkP7F7iGW3OWKLrgC6gDlSu++7aacrQnllMWCk9v3Tynd7B0m5LaN1lgflzOpqYHslh/5Gb
GlqSpQXJIad1V8mhr+lolEqOmeRQuwYH7nlJGvJmTvTXk/bxLBpK2YMxzV2KlY5Ks6z4VXOW
a8OMuWhy6KRGpjtTfqW8QFq34jVwO+gxG07v/pxlE8oRFnZfjVVvXvfXed1vmuLNBT3+D+zu
rrtcUXp3YHdXZoVA9+6B3dtVWVIntKvywO7OyuYCdt0N7F56Z6llkH4O7AqCdylr4sfuacjQ
nqjk+81H/ZQSbVSrgIlSX7RksOLGiXQuGkpanbBqKVKqEDrJu8JegkyuzTLmouHUuefWVYkr
2oSS+hodkJu03WnH8HBr5EW8SzbOhvas+ItxSRLyWg1oLppIwInUytaLMPqiX5S2ux6v+pre
nJjirdpNzS966O/m3XK3gN5tl95TtKAxsLvTdgXmdQd2e9oOHad4QXez9q5gv93Abk/aCSi7
OrB7WR2lzOD2Dux3p+1OR4b20JGhWKZSYjIzM9rfbisSXaXfTFJMRkM1R3+aU9UuMBFalLa7
9rmdjUaZ/bCVbB4VqJkRi747bXcaMjyKxn8Efnclp929UVZYtHfNuOxN2m4qmuwXNWuFi78Z
C3Wwr2VH2m4ynNfMvGY14cyg5uk7bfe3Ft8roJrnAd1L7moKG0t4mqKvsMN+KL6HkuOB3Zu0
q4k7mrQ7sLuTdgU14B3Y3Um7AiqQHtDvTtmdjgztmVuGqFThkp1CgGW/WLMkY3dtljEXTCTf
GknR0lrJsIXqminZu4zdVDScWnNqZ+wUr6I/hDWtaflSSPDXc/bxdGskMxOJaOeGqmr6ou/O
2E1FE7m36rchEjY2AW24fdWKyZDbjN3k5hCZxcRvloYqZPmiqVvET2d236K8R+iACq+YUls2
47Fde89gQdsDu70LkMEpsIHdXiZuqJfHgd26vxqdmwbOBB7Yrd+f9lQFPGgHdu/n05QZPGsG
dsHLhOmqsOpc4PSLaM+8PKxUZclCbKhcj6xJKNZLhYnPyWhK4lKcA5hWbYzeCNKKFheydjNW
ORmNXwSc1ZTSnHOCvVllUQruUk3w15P28SwaSuxv4eyMSWphMJcRi5YkFG9Y52Q00rVma6Qx
54FOvH6vFvfXfDBcu18GilWzhk7ezPms/HTO+U/S31NCTVoP7F6KV1LPCt61D+xuitcL4wp8
ZYUR6DOJ5YJSqIHd+v1ZVDHAQZmB3fr5miSuYGllYJdQvKtxAj94T9+I9kTMv8ZR1bKzu6zc
K9axXpecVU7xbg7eqWhKota7Sg3OamD/fVmjJWjtJq84GU2nuPu1opk7OnXni5ZQvJsE9mkb
8SiakOTVomLM2UTgCd4l0dxRvMlowg+wt2bSioGWHos4Hl1WwL+mo1G/GnXSQi/HFTQf/+4E
XMTxtovvVbCL/YDupnaGelO+oLuJnXWQGA/s1r1tnMwqtrkDu5fYtVQFJO4Duzt3R+Bv44Au
oXU3UrenO0N75jURxTthNc5koPhHWTJFcC+9NxmNmnI9dAQzKNzri1ZQbrMbpdupaMS/5tpb
plakMGho4IvWuDPcSACd7gyPoqFEVnJl/6FmVpg6rBCsupfem42GpDs7VSJ/2lCSSmtI6s2s
+FQ0fi8Wq509FKlOutF5lblH7c3rfo72XmlYseaA7qV3mirawDSwewmepQIayx3QrXtLxCmj
ftoHdi99Mmce2HvmgO7d2+yUraBNTQO8oh2wXBO8fjoz9GfODIVaZT+pTK2AeTtd4mVANV93
4M9FI6n1SNgZt1zQYqYsaaEj0+tjd3ZvIp9aKERApBGqvLciQ8yZrxsC+2nM8CgaSlWdRIjW
GC6CGwJXmPCx/PmT9jAaJzc1RqRyK1QVrYDkNVLRd+LKs5tTmv9guFvjXCu6OW9x5QWjHtuV
92oFf30Du5fWhRAqOOA/sHuP/hqDpfAI74py54PdFUrWsUP8gG797kSSGeh4MLB7Px+niqo+
DuwKUsfXahn9NGXoT6Tyna6LUGvSLISIwUGCFS1dzumuVVlmg6Hae9VKGvO04PxXWtIKae26
C2p6a1ruufptWQWWKljE6S7rfb8etI9n0eRkof8TJhNV8LyQreB0d/O7s9FEkZy4sl8dKtim
umh89zqar/m9aZLVHzQnqLmjontzLdhvSvcjRPeog932A7u7HssFHWs7sLsrsvzA7JZ3m90W
SdLBfOzA7mVPTndflRSEPR3YvZ+vx4QEyO4O7JKa7LVJVT8NGfpDewlVIzI2P33BB3aRNeyr
3ePq0J2MJoiqhAZxMcLlWda02l0PVs5GI91MpImKOc0Do1nTsi83yeHTj+FRNKFR5NxOS+2N
ULn+ZfIs18Pic9E4UyvSNZyInatm8Jocq765KDsbToxScNSX/XqE+njGqjfB+8sEb7vsXgUJ
/AHdnbEzdNx5YLdn7DJYKB7Y3Tm7xgUcijyw27N2ivKmA7s9a8dgyWJgl/C6q/PJT9vTkaE/
c2TI/ib3xy9TRWUOeYmFAdVLz97P6WBIS+7qX7blBs4u7sjazW5NK01blawd7YrdkbU7/Rge
RfPK2nkgYballcA2ix1pu8lwGpE/aM1/NJkarFP3/Xm72d1p1KOX109Kv+ehvO6duFvB635T
4o5BXbYDujttZwWU5hzY3Wm7kvFBisDu3d2aKjiAekD3kqcS5mbYtzewWz+f32dMwKdvYJf0
2d10P51uDP2ZG4OZdbXChRSvYq5I0VO5FA35nI6GwqBKnAplFkaN3Va0t5Pp9XzsbDS1+K50
/8/L5BaMZsXAE+dLv95fT9rHs2govUSIQwSldFSpjlZx1Zvq/1Q0TtM4d261OR/KAv5wYtWC
cO40lWfD6c1UKURdWiZFc5D/nprK/LdX3nvEU0CKsuAduYAK/y49QNhe5MDupcKSCoGZpoHd
ToUV7AAY2K37yy34N7jBJ3h3DbuhNmYv6NZP10vyIwl7jwzskkznTX/iaWLRH9k+WJLOFI4P
L5MRdEhKVhR9X013VxxlKhx+ja5qbr3UDltyrJhcJavXBiNzwdRkVNiaWViUCVZ1ikVLyPC1
LFE/PSyeRuPMUamYE2ICm2d80YLfDb9Mle8ftIfRZP+au7UaTZfsFxbsUfNVS9xf7CarPhUO
pdbJHzThriygzi5NTmv9dC78T1IEjNs2qggY2L0kz891tI1tYPeSPEsEX+sP7F6SZ5aYYfPd
A7yX5EVPD+hOPbBbP59qnMGw7HNgl9C8m5zn6WfRH7kMaKLGbCQ1KlrgLHwsWkLzblJRc+GE
D7NwmFrUVtHZeV+0guf1a/WYuWhi6tkfbI+m54oKz60ZlXaed9OpeBpaPIqmptI1sxCL2euv
h3heXdF3yZcc/HMymtDBpVLMGV5XbWAvSKxasTk3ys9z4YTyMytly/4ysAIrP78bFRfxvO2q
gFYJlgUM7G6Ch07w8qIJ3oe6gBW9Cx3YvfSuU0JbwQd2L7lrft1FC9oHdm8OLyfYd21gV5A7
vnZa6KdvRH8k528puq2cOYjWDH7hr0VLyN3NGMpUOJyEiDo3Z6y1o/oDvmhJEu/mxJ2KpiYx
pS6RW7GGej6mFa86/z3dDDydzhGPoimJOGsjo9z8GoG9e8qkW9kfsl7X9jFz0WR/JRpbV+7N
GStYrvFVS5RjLn3+vibDocQmfoMofpvQBls481T2+03ufo40oKCV2oHdy/E0hr1gccDA7k7i
ldLhwldgN7M8f+EwSOJP8F6eF3ki8Bsc2K2fzwQ3RhnYJTzv2m6hn+YR/ZGkvyYtvdZCUhiU
TI41S7zbLvWsPyejYSfU0q2YtNy1wdI4S2q1l17OX5PRlBQlUxHlUhStqfiiNbXam/mn0zzi
YTTZWNT/0TuhCYSyZG9Y6g3Nm4om/A6C5nFRLc7D0RxeXTOVctMWMBVOjIJ3qVw8IiXYi25u
FPxN836vQKAwKjNyYPdSu2ilB3u0BnYvtYv2EQW1Eg7s1v0NOWIBUwIDu3t/SdHx1wO79fMV
DlFM8HQ6sEuI3c0U6Gkf0Z+I+muY8jYtGoefgB5nusiU91IU53MymrDE0lxFrIf6CipVUpbk
7/rNDOhUNJzUOVATZxBNpaHzNbZERuZyevrXk/bxNJrq/MfYaUPhDGri8yLl5xvHtrlocngJ
SRdt/qxxA4ef8qJxoXqTv5sK50XsYkS/ZPN/oF0Nb2K3gtj9pmnjXMAX5MDuLs8S2v00sLsL
tFLR1N2B3czvJFWwSDKwe/c3x78SzLwc2L2JxRjcAcVfB3YBh7hx9uA83CPi/zzhdyJc/K5e
ai5oYUYn/db/wO8uxdsmo6HQPegU09NcawbzkImX6MnYpXbbZDTxWmUruZiGogzK71Zo/XC+
jObXk/bxNJqiIXvonNUZHlo6X/Ha5nw9zDMZTE6l9ea3oqxVWgc9ZHzVksbIazWZ6XDCOTQa
cNl/lKhaaKx687u/zO+2qwSWAmqwD+zuxE7M+6CJncBuT9yhUiMDu5nYWRJQMWBg9+6v+HEL
D0fzZl+ZIqE4Df46Duz3pu387DqpwxNZf02N2VlDqCVXtBCjS/Qw/N93lRr6nIzGX0PWmGKu
QpUNzT6suBI4b7+sx05GE9UGKqX3Xqufthh14EW6etdpuzOaj6fR1O4kqFDX2gztBUkrjCxZ
rh15J6Pxm6TfhbpToSrSpaKyenUJTb1O202GQynXKJb7j6c6uQPLOb7oTev+Oq37TWm7ouBT
O7C703aloWYEB3Z32q4yyu4O7GZ2V/G69gnezd+LgWKxA7s3cVec5cBKhm2F/NN92o5PDvFE
1l+ThBCdVfNjt6NTwKvGKq6Oqc/JaCjy3+ZxUKOaQQtbX7QkbdevJoC/JqPhRNE+mGvurRSD
lV7W9Ntdjmef0Xw8jab0bP6eI9Jq6EjXmkQX1xt+NxVNtCB3av60aSEBJ4CjlvvdabvJaJrz
waLUWic/i1Cll7lr3k/nd/IdOoFgC8+S7p1lwx7b9fiaP3yoHl9gd2ec/KhEM059TkTzLxWK
0b7fgd26u+wsSApYKT7BW79B1dQVF0IJ7NbP18MtBrxTDOySnOKlZLCfRCeveWI5QL63L+dT
LoULONb1WrSCdF6OJn9OhlNSjhJebuK8M6Pvr5SXWMrZDemciqYmj4MKVSml5IylSOsi17JL
2Zlfj9rH072xnFvR3As7WcNoWlnU2Sg36eupaPymUoT92uS/bM6gyn8sWlLHv+qh/ZqOpvvz
26oKZw8LHeV9G8otY3e/S48PNSIf2L0kT1NTkOS9oLtJXq+4+0hgt+6uZE21w2J3B3hvYdaJ
kYEfcGD37jCxP/SoqPwAL6F5N31a5WQSj5whmhMj7qyirYuAOlxtiTWE07zLRvzJcGJIQsxK
dmLkBxfaRLfiBUHWb1oCp6LR5MduzdX5t/8BEqNYtITmXU6Nn9F8PI0mmxO9ni2TR4NmsReZ
kNzkFqeiyan7xlgz9ftRN3A40letSPzS5XXvazIcDslV59+ZjQo8Spn4PfKxiOdt1+PTAhrn
DOxugofqhx3Q3QTPFGx+Gdi9WbwexXTUUGyAt36DZqkx2Hk3sJsJXkmk6HV3gJcQvJvacT05
xENfDfU3ux8ZRE1QwWVbQiKo9Euxlslwir+LJGePhbhVsBM/Fi0heJcKGpPRaNjUZj91xbKi
AvO6yKX2ckL516P28XRvqLHWGiM5TUFdoLJE2pvpjuBNRUMvr5ws7D8btoy2KdCKrCRdeuZ9
TUejVHsvjaSKVLSpdq4h+83vfpAkHzhJdkD3kjxLaPfdAd1LASwVVBLlBd2bw6P+wKR3gPfm
8DRVQ116D+ze/eWcnBehxpAHeAnFu9TC5awni3ikpd9CqNhf7jVTbg08qdqiUm2+KaBNhcNJ
1Xp4c0U3O0jxfNEaPb6bAtpUNJo6F7NeLETsDM3hrRAIcIp30xWgJ414Ek2J2Zzsr2LnrAQa
wZUlozksl221n5PB5KSVC/ktIteONqLmJTKWfh27uUtMRUOR+pYW89Y5ho1Qhvce6v3r0x/b
1fgYu8e/kLvb70TAxM7A7j31o1oI2rkP7Na9bRpu4FgiYGC3fn8iyQqokTuwe1lnDIlnWMko
sCs4Xb5pxLeTNjxza6ilWW/sBxQbbLm6whCAXt1+VyftVDScKGplyo07oY9PLFpB6e5Geiej
Mamdauncq4GUzhet6b676QCwkzc83JusVrhW1jAI2TrAcjkk8TkZjV/TyESdzVVlBT11Zmck
nkz0TkUTmnrNau89CzE4SUmTmkBvTvcjhPgYbG4/oNursgWV4T2wu+uywqBM28Bu3d3oBBMG
p+pO8PbGSlQIcmD30rueuIF3nxd0ScLu0tWAczsJxBPhfP/iLMZfW29ZGRRq8EUr0o9Fb8jd
VDSUtJRcc1X/uxs4jECrSrJXe/M1GY2kcLCrUpk8LMGSQr5oTb7upvrfTgLxzNtEa3NGVDI3
IfBeFAnYFSmufJOwm4omJ5VasvbsXKgpmGbISx41/6Q3A71T4VAiVaMSwy+saN4+0dsm7a+z
u/0yfAL2Yw3s7qxdAcfjD+j2nF1FJxAP7N6cnYXVGfYyGtjtOTtroC3agd1L6vyRQi+3A7uE
1t2Io/WTOjyRza/Jz9qeOzUqRmDHUF0ijnafs5uKJtJvlvPLsMoaqDEZ3ivfnbObjMai/Oos
qDh7INg9Y4kM313Orp/M4eHexMg3O00tCt/IN+TspqKJnF0NaZNexPx/qE7L9yftpsKJ/Jv1
bup/NRF4rL5l+P7eMnzoPNPAbk/bMdjoNLC703ZoTiyQ21N2jNponuDdXZSo9cgB3Z2wI9hZ
5sAu4XbX9Vg63RnomXNG4zCs6kLN/4RTdkumKNr1mOxcNJTUnAlVZ42vP9GU3RKJ5ZuU3Vw0
nHrrXK3nMDMAe3Z90RJ3hpuUHZ3uDA+j0aKam9BLUhBuf1zRlfZy6rh/0h5GE+1yWbPFoVcE
9UVbEgzfDFHMBUN+JfIfTM7Nqr8N0J/N3IHw05ndtwjwEdyPveJVtGy4Y7sEn6GtDQO7O5uI
FukO6PYisaBevAd2L+P0Levo4MQJ3voNak+KFi1f0L2friVFBd4GdgXjlGtVNDqNI+iJmr+T
4ZYrWbT/+dmJ/Z76kmlKZx7X+ntz0ZTEGqK15WVfa2AJf5FX26WUydd0NNS7WDbJ0tHbgEez
RLHuckTl15P28SyaKHn7I8atFioVzPTGoiXZxJu7zVQ0McfYc23aJTOjA+9LxNI9mqvfzdd8
NJF85wiJQJEZXzP1EvjpjPMfJb+XwSGFgd1L8EoCH8UXcje962BjyAHdurMcNiKgytrAbv32
jBILWCoe2K2fr7VkFax3DewScnethUanawQ98sDgZK1ZEc6NYAsanrTg/AO7uzlzp8IJamNC
oTAh0ipW+fZFKwaQ7bLy/TUZTU1cOBoaayW/vYAyqGmFBqWzu+tmUzptI57uTa8xdyMlOhrB
VHySNXzoT5+0h9E4USNhrWq+QQW004tFKxoaL6P5mo7GNLcSNxRCBW1jzZvdrWF320X3DHQp
P6C7SR06yhbI3aSuweLjB3Zvzk45gaYZB3QvqWsPxPbafrE9J5JmYD57YJeQumv9MzpdGeiJ
Vn5P2nLmqn7MtgKy/L6mqnqntDcXTfEPxv5dB6HLYPdtWVUivu7Jmg2GVaxVKz3sUVEStOI1
wvmSoP560D6eRcPOzoo/YKUYhyMgWCJeQumuR90/J6OhRFSs+f5Q5w66V9OqZsZrGZbZaELd
urBUax2U7KbJ8aE3pftBOnuo3u7A7u4ArLDswoHdy+8soZKUgdybsmuUuqBWmAO8u+JZqoAF
2QO7d3dJkhbUxniAlzC8a/kzOg0Z6JFbhoYorIifVZ0JrS3pElFYP1WuG+/nwpHUcy9EpsVy
RVV9llgYkLWb7qypaDS8azOZ709WBdN2usa7Nl8y1l+P2sfjvSm9aIv5Xaet2NvRFy1pA/zz
J+1hNNk/WOvi94nWjRTtA1zRKH8rpjwXDaXanav6ncspeAVbM2hy0OtN8n6v1J6fRfjgbt5s
RMWcFO2ZHNi9R3/1wxyUsxvYvZX2lvyNhKWeBnbr9xfjuGg5e2B3f75SwNTdwK4gdnRD7E4j
Bnoij+9fXbUYtKhccgN9w2SyEvMHXncVzedkNDG6250CaW+9CtiquWh0t122Dn7NRyNO6opm
CQMTeBB5STn2rvJ/GjE8iiZqkb1XFaEsAieIVoy8347uzkUTo7vqP8dauYlVwqpbq0Z3L8P5
mg8nmzpD9SdNMoGDUXnSkOXN7H6E4F50RaCzu4HdXZVltDY2sLsrswz2Yx3QrbvbOHEHd3dg
99KnmozAuvbAbv18xV9tiqopH9glebtrvQw6TRjoiTZ+TbmK9pCnExNYTXlOkuG/0zu+OXSn
ovHXUHf20Ft2CkGoD7YvWkLvbnqgJqOpubOEWkYXBV0YeEkVgLPdzFKcLgyPoqHUnQVV/4v9
t4D689CatF2Wq97Bz8lo/Cdd/BIR88i5lK4wvVtikfHnj9rjcLr2bFJEpTYFZQl81Vtx76/T
u+2Ke2gbciB3J+0MVSl4Qben7ETAXrsDuzdlFyohYD/SwO7ldCXIBvZqGdjtKUWzB2qAtqYW
e6OTcbow0BNtfP9oTaIHvL5klEES7YtWdNu1m5N2KhqnZ9aYmoUWLOMOGSuiaZflvq/5aJzP
VVJhaYQaUS9JQN6n7E4XhkfR0EtyMkzpam4GKhvsSNlNRRPZqt6NKPvNpBLYN7IjZTcdjgg7
2Q6HazLUxe2dslvB6X5Tyk4yKCDwgu5O2FlFu8UO7O6EXRGQngzs1t3tOcVIJNY7f2B30ztF
9fYGdm/KriRuYMV4YJfQu5tEyunDQE/E8WuKamwkhtS0MlaJqUusRsN39vrQnYomTLZ6tuBE
RayjSa4VPe5O7276nyaj0ZefLXFuKmA3F09ajf4hK3QjtHPaMDzdG3byoNSzlgq2qUZR+rvp
3VQ0L3pHnUlKVhJQ6XqDmPJcOCGmrKpUoqPTwJmqv6uY8j7u9n/+9V//+n//+q///Z//4b+n
nP/jf/6v//ufW48p7NaxW4cYZEV/+qn+PwAAAP//7F0Ljuw2krwRwfzxc4EGtvv+99nMEvUW
mIHkEM1m99o1Y3sMTBCvsqgSg/mJ2MK+f0h6sCioTDOwe9l39JiB+ziw+9k3WFAd2N37y4Qa
EB7Yrd+fxXA3mJwe2L37K5ZyBr/AE7zgdUJ2w4pOwwx6ZjHRu4lzVcrshBjtiMxLJl34qgHg
czIa/6lbKKg5/eZSwIZuX7SmI/Iqmq/JaJr/8Eq1UlWsVzAaX7SC4l1XZf88aR/Posn+pDkD
d+rtV6PWQcu9vEa/+3pG7HMyHEqkUZSwquZ3JFShZkm7qlxqQ35NRsOpUpdMfm3lCt/05kpG
P02/f1dy9Wf1B6lXWH8wsHtZnkXbMfYsvqB7OUBNuaB2dQd2N8erDfslH9C9DK8l6eCRNrB7
d5d7EjAdObBL8qvXsnB8mmbwQ9OMKM/mbLmQgRMvvmhFtviO381FE66AuWUq2l/t+yi/WxFN
u/S5/ZqMpiarTlL9HzXUf0FdibSiUeiW3/HpmvEomhe/i+ZbrVydfcDDv9/N7+bCCT8PYS3U
ndhn+14TkP/Mr7Zrrcu5aDgeNYkqmmWrjLrNzD1qb4L3CyQI/fkApdYO7G5mVzI67nJgd+fv
qoLNcwO7l7mrEzZUOfzAbv3+Sk/ZUHOOA7t3f5VTE1Af7gQv4XfXGnF8WlTwM1MHflnLRwld
YPdnX7SE312LEc5Foyn0Gp1La5bgeKB+34reEOd310mVuWhasjBBEdXeegbZalvSpn5Tcf7z
pH08iyb7aySHcHW33gxtbshLOnFv6OrndDg9ygalZpUQ3oHp6pJwLt8DX5PhcMriP5qmqgYr
ReapJ+1N736LHKH/uFCl94Hdy/JKauAZe0B35++UQQ41sHs5noUyL5ghO7B7OZ4kPwxA+bUD
u7lGW6IxASTxA7yiRtuuNeL4NKrgJ/YBkqgbU7HCvSt48MoSGzJ6sfirg3cymuLXzd7JJAc9
AqNZsjctX5sSz0VTU3PuYBwmcaygV2ws+m6OdxpVPIom2FrN3V91reRm4NsxL/GrYbEbjjcZ
TuvUnRURaam1wEMjS7QiL4fOvybDCc1ZsjAnbx4MWLiLRW+W93dZ3n49QkKFpgd2L7NjZ5Ng
d/sLuvfktwQ6j76QW3eWe4xSg6T4wO7d2Z4aqvQzsLvrxgaPhR/YJXm7G053OlXwM/+A5q9w
6hr3CgNpvi9aY/t7w+lmo2ndSV0OtTvY2mHFMeuU7iaVMhWMpJpbDsvf1nF+WpdYj12OaP95
zj6eBZOjscuI2VSUDdSjyJOtXf9Zlb3xl54Oh5W1dCXnQAorTC8J53rk/GsynJgep+Kczl8C
XDLojTDZz/BmdL9ChzB3cPZsYHcXZgnsejqgu8uyYqAN+8Bu3V3JkeYCJUoO7Nbvz/9MQw06
BnYvuSupGzz14dAl6brrkQo+DSr4mW1A8y8u8lvGuaA3kSUpIdLLzqHP+WhKFZMeyigGlmSD
3S7hdtdzpnPRSNLGxpZz7dpAxXpZMm7u5O5azpxPg4pH0QS5s1ylUS3mBALV7ft+cjcbTjDU
Li8n44Jz1TUF85t7xFQ45AeQUOsUlVlC3RF80Zvc/W1yt1+FMIO9NwO7O13XMyhSOrDbE3bN
wErdgd2dtNPcwHbFA7s9aZdB1v6C7k7ZFXRWdmBXpOz0htedBhX8zNKhFcnq5xP5Ox2mdWu8
Q24ydrPBtEaFcmGOUt+vSdlNRSMvzXSnDUYVtdFZlbG7mnH585h9PIslLOGbE9Tu/xPmYzAL
+t4E5Od8ODE647EQaWfQTHFHxm4qnPB1odZy/G6Mwbt+LHqTur9P6n5KhpDAKdSB3Z2x0w5y
p4HdnbMz1DpsYHfn7AgV8B/Y3Tk7IVTH+cBuz9k1cH8HdknW7iaXcvpT8DNHh1diSJm5K6PK
maktyD1E+9j1qTsbjXDrJbOZVFTxak00ja6t4eaiCQWnF++OWiYXjKzGou/O2p32FI+iCUYk
JtqCeRPYa7GI38mlPvvn34imGLP/IrNyzvBYyBp+d3OTmAqHkoQGYa+9lNAR+lcn7QTmd0/6
xrEHvqwohyyb79gvvyco5zywezmnJv+tw251gf2BOjHMOQO7O1/ciOF8cWC3fn+Fkxl4MA3s
3v3NkpjRBugBXsE67drdhE8HDX7moGFWggWQH82KDkulJZVv45ta8VQ0Ehya2JwPVCawki+r
WOdNqmcqmhKX+WaUu/+ngHp1sWgJsbkRAjoNNB5FEx5vrBb9DtyLgh2nec2kyiuBcv+oPQyH
kpNnNcvCpWW4yWLFQcTEN20JU9Fw8hBay2b+pFlDdePnUhG/nXX+m/T3BG3HGti9NK+k1lFX
pwO7m+b1gvZVHNjd+5sr2K44sHtTd5qogsZQA7t3f6UlraAJywleUTq+O3xPJw1+5j0RPfhi
rXeVDPZp8RK72Jh8vD57p6KJeWRuVBo5ZcUnJNYYE9O1s9hcNC1RIW3+d3RpgRO8bY3Q260K
32mk8Sia0NMLAb5WnX9Tg1Valqjw5cus/OdkOORvxUImTTs7D0dHXlfUaPyD3gg+TkUTLq/Z
fzCUM2tHVVrqPzK3+K8Q4RMGj9eB3V059l8UXDkO7G561xRMIgzsXnqnyVCPgYHd+v3VUJsH
O1QGdnPXZ05k6Dt9gJd0Bt4cuqdRAz+znfDfbq9ZSYp0QgnRiufBv5ebNvypaDRxaHE4CyZq
DO6PLrGdcHp3bWI3F01L3a8GzQmEkFRQ0SQWLcni3Yzznj4Nj6LJqVZrfhFrxTdJFZ5//XYR
vqlwnKkRVVLnd1lQRhSLlkRz06YwFU2YBRoXbk26bxHYkD1pCfLmd79Iha8/UOHru1X4auIK
0qiB3UsDalIDG/AGdi/Nc+qbCcySHdi9xdqcrIL9agO7neYJo2naAV7SInit2SKnX4M8c5/w
E126lhZiYmBifJkO31U0n9PRaKXcrbXcO+FeGksGe+lqauJrMpqWitMIsxpUr4DWgbHom2me
nHYNj6IJwtaLWI/RUa0NHppYksW7TH9/TofTLK6/VKUUUfCXk5fMTt3yvLlwwklaVKLtqveC
ZlAmVcrfPO9ndfgUVI08oHuZnSQRtA3vwG4++VOpYJvbwG7dXS5JKjhaMbBbvz/h8NzDzuUX
dOun05IK6h44sEuSdzdn7enSIE+U8ymVJtlKDPSZgtr5sWgFq5Pr5N1cNJyyqWZ+zSdmsJoZ
i5awuuuC2Ww00YhvjbUJLpu5yKPh0u/tz5P28SyanJyYUuE//wBp0IpW+BuS+jkdTtyCPJCw
we0Kpr0X5SL5RhpoLhxKMULu8TCJwm1Fid7qygtY3Q9N9hKqsfyC7m6+85sf3HwX2N3VWcng
PXtgt+6u5KTojMXA7iV3r3ommEM6sHubA3vqHfz+BnYJvbtWbZHToEGeiea3YlIqWYv0Ayx0
ssQg7VJ+4nM+Gu2tkIRAMWoZ64uW0Lsb2Za5aMTvfD1Uo6uRUIOtQNbQu6uRhD9P2sezaGKm
ldS0xFVCGjh/tmgSli4353M+HD/zrJZcG7WO/XA26LbMRROiyUJO60RKh91830LLC8jdfi2+
AvaMD+zupJ3fLsCk04HdnbSr6FDAwO5O2jETnLQL7O6kHWdwkHNgd6ftKoNDKQO7hNddq2jI
6dIgz6Tz/ZgVdipkVRXtH/BFS3jdTS5lKhr2CxypNq01SmWgVKcvWhBNvaz3fU1H0wtT9Vha
hIRm7dZU+65nd+T0aHgUTGTtnAI5ccg1F2moHt+KYtB91m4ynPDNUCtG/l1lOGm34D50n7Sb
iiaSdppjrrnFPDuqc/Quxa7gdT+UtFMCa54Duz1th44sDuzutF30L6Fpu8DuTttJAd+xA7s7
bdcMfP4Gdnc3oB+8cDdgYJf02t2k7U6jBnlqoqEhHJRjDg+dAlpjomFyPcY4HU0VpV6pd6OO
qootMtG4SdtNRSOphExn6xbJrgqn7RYkIW/yXH+etI9n0bwE7Jxnae+1oh5ci/Jc8tdP2vNo
uKqEuYn43RfMEC/z0LhJ202FE8rJrVkpJYeZDtqc8c/M232LHB8xeHXmFXmAZaMe2wX5rIEz
AAO7vRMQFVke2P3FYuycOKB7OaemoiBnH9i9nK4nLuAg78Bu/3wC/joGdgXn7DdM4HSRkCfa
/tGirc0Pmt5EGizGtyLBfDvGOxeNJtZaQ5e3+r80jNf4ohWl4tpvEj3T0ZhfprRQ5g6ytDXR
MF2mrf48aR/Posmp9NY8jmwtqyk837FglOiGpX1OhkNJes1+Fyfr3EBjeGdp3xvN19+Ipgj5
j6fULrAn71Qwv51y/qu0+Bi1MTiwexmeplbRsueB3c3wegbL2gO7vS2ggXW1gd3LoUpqrYAc
78Du3d9MfmaBL8MDu4Lj2Q3HO60k5Im+Pyc1P6tCI621yqgG1xJLOpOrqdfPyWgkTJD96zZl
kwZ60smSSmtYzl4fvFPRlJRJixU/eSsJ6hOwRg3kTnBZTieJR9Hk1JyuRoGilMYG/nbyEjVs
zpc/nM/JcJwVcWjwkf+ndvAk8kUroqEbm4+5aDhlzi8NHYrrEXrVmxPgfZO83yDFZ6DS8sDu
Zne1oUrLB3Y3u2ugr+YB3Zu/6ymjFngDu/XbqzUx2rMwsFs/XytJGfx1DOySlsArNuQn7mnY
IM9U9IW5VKLMBZ2ujDULgtF+7as1F4z6HaSyZa3GzcDhSl+0QmT5JRd1dd5ORWOJRLn2rtyL
gVPjNjlc+Z/s4dKP7s+D9vEsmpzMrPqzZiU3jwsVWV6hrHUrsjwXDvkrsZqWkP4StDeYEi1J
3112jnxNR8PclJuH4kEpSlT5Pce7itr9kApfF5BBDezuvsCQmED7AgO7l+HV5KQX/LEc2N0V
+I56aQzs3vyd+jMFco6B3bu/HAI7qJfGAK9geXd5ldOvQZ6J6DczUWm9F9aMKpys6GMlu7FP
nYtGUg35vexHVa4F1JqSJWaw1C5dub4mo6mJmodhTZ3kdTC7GouW0LxrWW857RoeRRP11nBM
czJRnXWBXbXLqrQ3yeLJcLo/wP6b4SaWBbzw+aol88l3ZdqpcCjVSlWpkN8rCFWimBxkefO8
n1XhkwzakQ7sXm7Hfu0GyxUDu/fstxBHxXX4aK59dn6k10/nDHK7gd36/Yn4d4KO9B7YvZ9P
cYXvgV2Sv7vRRzutGuSZG4CWbFScEZF2+I2+pDarl92En5PRhGQUFz+hWucMJ/d90ZIE3k1W
ZTaabmRWerilZTSaFdrXzuxuNB9Pp4ZH0UQCLyQSs/MgEYNnem1FO+HtTO9kOM0JUOnNmv9y
GqgqFau+tXL+NR8OxwXeWV32axH4sM1Wzt/U7hdI8VHqaIfyC7q7OssMKkwM7O7qLBuqBXZg
9/K7qBmC5bgXdDt7gqvHB3br5wvtZFyvpSyRa7nLpejpz6BPNPMpFTarTiGaszuD5VoWFACd
hl1XzOaicTaU/RbnpxRJEzAaX7Qia3cn1zIbTStO7krO/pdUtCdyxXQy06Xh258n7eNZNNmf
tB5Vc2nVGRHMHr5dr2U2nEalM3XNrbYMi0avMOsMJeS/etYehkMpXi6lizSjjM6eTv5y3tTu
Z4X4CtgZcUB35+yqoTJ8B3Z7zi6DSYOB3Z2zq7A89YHdn7MD+4wGdjfrFMFZZ2C/OWenp0OD
PlPND4nYEo3hwvX35OzmonnJvPsSbTkUidEWwjU5uxtPtNloOGcmrqHi1Auqw7ckZ5frddOd
nv4Mj6LJybQ4Z5CoX3aGBYm/PWc3G05Uyv0XE7JAcGfGhpzddDisPXfJGnli2LFujqa+id2v
UOJj1P7pBd2dswM/3Au5O1+nBJ79A7uX29Uk2mHH4MDu5nbNQHn9gd2bsevJDyiwX+HALuF2
14YGetoz6DPN/FKimC0i2So4guCL1lhnXEXzORkNp+yXzC4SxeUMVhti0Qpu12/O26loJOXc
YppCsv8T7IKURbOy5XpyR093hkfRhMdZab1HUtVKBfVJ8xpJwVtuNxlOy07uqLCp3yLAsf5Y
tSKcdhXO12Q4lKg09lueWi4C9qj6on9kpx1/hwgfOFu5YlTtEU8BKcqCN+QCGvxDwoAlg1Rk
YPfSYHH6CErHDex2KmxoNfDAbt3fLkkaeDcf2K3fn5XUO5jGHti9+6uawPMikEto8PXAiZ5u
FvrEYyBmYYxMs9NGbqAgmC0yCObrKYC5aMJSSIrFpVLEQINgWZOwbXRDg6eiaak6b1Qnj426
gTS4rXGzyPVanEhPN4tH0VBqjUtlqmExAw/irpDAZ76Rop6NJi5afnUUUWuwsfaKZLrf8/7y
SXsYDSe/neSsIXwONyf7onfhehWx+yFZQPR3eED3sjvzKyOYaBrYvad/Tf6SBF9jB3Yvu9NU
wBaUA7qX2zV8Yndg9+6utJQ7ekkc4BUM70aOV09DC33iMmAp/Cyqn1VaszHGImLRdzO8qWic
rInVHrORLTd0Lijpimja5ajG12Q0/tg0M3POyvxqfYQIXl4gg3NP8E47i0fBBFcTph7Ghbkw
mlFfQvCu84Kf09FQqfGgGfdsOMFbYiXXrtUn56KJJqXGOfvmKHVw3DQ6w94Ebw3B2y4JSOjQ
7sDu5nYFLLkd0N15O38ZwzZygd26u5TF35qgrucJ3voNlh7XY4zdDezmBtSWlMDS1QlewCBe
jRFXh+5pHaFP9PxL4lyKNsvSC6qh7otWDGu8yOTVoTsVjSYSClXhLr1Vwg5dXaKkRy8LpKtD
dyqanrRopag7+L907H3Xl2QjOV+2GPx50j6eRUNJa4j5FMsh+wy+fdKKrAFTvnb1mIsmpxif
8T23Ek19HR2S7iu4N13ObH1NhsMx+FhL2MhkU9hie24a8c3vfosuICW/2WObPbB7aV5JLaO9
dgd2dwpPGU/hBXYz0dN0XG0honeA9xI9SaD2zgu5meRxUnTO4QQvKdLeZFZO7wh9Iuhvqdee
Ww6/YKaCFmn7miLtTa/iVDSSirSWtUpxkgfaEvmiNSm8m9LZVDQtVbVecs1hS4QKjU9mVv5r
vvimV/G0jngUTQwvFfHXSBcraJtvMMMVZU27IXlT0eTUekxKc+mFYWGfWLWEs17LFM2Fw35R
1latSpPaFW3ynRPsepO8nxUFVNQjaGD3EjtOfhfEB4z79vxOqrCnx4Hdu79+nKHF2YHdu789
tSJgleDA7qWdnHIGb7kDuyJ7pze12dM5Qp+ZekTjee7N/PAzwpoJeUmHF1m+IXZT0VAct37s
aXEO3EGhNlpy2lK9HMn9moxGUudWzF8NmeGJJ1+0xuHsL5+0j6d7k01q9KuFbRtYN49FS5jQ
Xz5pD6PJqcYQtlom56n4uPSKBuGb1OrX9OZo922REMGhYqgrr71deRcQu5+SBOzo+X9gd9dn
icHPN7C7K7SCFrsGdu/+ahIFP9/Abv3+JKdSCRSQObB7+V1O1MDJmYFdkri7OXVPywh9ZudR
c9MWYhhhx4n2VS8xwLC7nvepaJyqVTGm2lXQvB0tUdKLXr/rM3cqGL9V1SJMTSRmRlB6t+Ii
cU/vTr+Ih1sTPWpHrqsIKFBCS+a//bm+afKcisaJmmTNhYo2Dwd8EcSqJfTu2sxjdnOc27Ff
847RJDSn+hZ8/vvsbrsqoBi2vwd0d9Kuo06tA7s9aVcErMYe2O1JOwWPvYHdnrQDxSUO6PaU
XQN7FQb2u1N2p1eEPvOKqKX51uauvVa0BvP9GbupYCL5Zq3EWGbNhjYapL5AyuM+YzcVTSTf
WhEybSwZbOD1RQty1/eU7jSKeLg3Tul8Z5oTEqeqWyndbcZuKprIvTk17VaaREskTOm+PWM3
uTmRepTKOQZ33vm6jYzup+QAUSOdgd2dr7OMChYf2N35OlNQyWNgd+frlMF30sDuztcZgz3K
A7v181lP3FCllgO7Il93aQT2P/5/DQZhz8winNuZ5VayH1RglYwXqaFcytZ+Tkbj7O5VIcsm
Vir4+PiiFYLPja740NdkNJKcoHZS4d6pgCOMseib2Z2dVhEP9yYbUQtPQJECT1N8ez12LpoX
u1Nt4m9Gzoon7Nawu+uE3ezmaOZuRqwkHb4W6T+S38l3aAKCD/ySnt9lMx771fdQZ82B3cs5
NfkvHeScB3Z7jbiBxnYDu3V/K/ufiQ7vHNjdCTtr2MziAd27u7kn7SBlP8FLOOe1eZydRhb2
xFzArxPUc5HqlKk10MhClwzTkPG1ychcNJIa5xqE00g7OKMuSwy9oi59TQSmoilxHyDTwjkr
egEra4rERNd2NnbaWDyKJuxsSmdnNp2to9Pva+aRiW4452Q0ryCsURVmWKBlRVErbGf+6kl7
GE0400jNVDplzeAY0aydzW+nnP8mBT6/zoJ5kwO7l+OV1NCX+MDu5ngd9Y8d2K3729kvhQVU
WD6we/N2mqiCcxQDu3d/taX8mnKERJYP8AqWdzNYaaelhT2xGbCkWrpUatVaA2emfdGKXJyW
m8ziVDSSqIuGkX0Ja10wMe2LlmQWb87eqWhaqqyFWhYuTiVQGb41yat6rehtp6HFo2goNSlZ
zPxa0cnQ4mRbUgVv1z2ns9HkWjTaAEO9TtBoVtzlWS4tGL8mo+EUTsfFRNmagm8BnuxQeLO8
XyDDxwoaaAzs7rJx9/sgWjYO7G56hyZEDujW3aXM4eyMyvAd4K3fX/XrLoMp2oHdvL/hKgL3
BRzgFV2BdnPonlYN9kRAv/iJo1wpO42QAkZUlhxTZJdCE5+T0ag/CmGJ5RRPO0q/Y9EKesfX
bYFz0URtpNQeEtiFGXwd+6IlIiB3F4nTquFRNJGPy12lUM3+ZcHTBGtEBa8FH2ejySS9OO/u
dKj8YfRuidPfHb2bioaTsPVqIWUT48kgvZP3pMcqevcjKnzZL09gEm9g97K8mriCjrwDu5cF
hLIe2Lw4sNt5HqreOrB7C7VhA48Py9oSm7lHcz09NUJbnAZ4San2WmzZTrsGe2al0RpJzdU5
V7hPgEm8Fc3AZHzVgvY5GY0krf7f4jxPckZdOpdovTlxuenZmoqmJydEIaVDqpLBKcu+xq/h
tlR7+jU8ioYiXRwCfE4gW4NnrVeki6MO+VdP2sNoctiUVyd6/uqRhostr+hEvRVbngsnGvyt
cvG7RBWQgb+1lv9/yvAJbIB7YPcyO0liYPVlYDef/AksLtIaS9EHeyuW/I0E9icd2K3fnXA8
T+DnO7BbP5/2lEFBkwO6hNFdvcr9nD0tGuyhbn6tRbPkQswKv8vXDHzc5O0mo3lJRHfrrywk
Kie4YmTUGd21OdpcNJKI6/8Fg5r5rjADueFAf560j2fROJspWkS7OE/1qwlGt2PVknCu7dFm
w6ktEnbV/EIUsnXoxMf3ur19TYZDiVqllil2Hh3GmWtneDO636G/x6AUysDu7rvLBEqhDOzu
wiyjfYEDu3d/JVX08w3sXnKXE+o+dkD3JhRjahLsqhzYJeTuZpr3tGawZ3r5pdXSi/jJ2xpo
m8FLCn9O7q7NDOaiicFcEsqt9kaksL3qig7C2m+KslPRSOrOVLUVp0IdHRiVJcoz99O8pzPD
w73x65c/ZD16IjvoeBSLVuS38g23m4rGWRp1K0rao8gM+hKvmua9HEn6mt4co1Aw7dlqFziX
OlcFe7O7n9XfK4wqtB3Y3fk6NdRW4cBuz9cZ+gM5sLtzdh1Wfjiwu3N2hOpsDOz2nB0q6z2w
S4jdTQ/Uac1gz2wzuDcm5tyJCkgeIkf63Vm7yWiyFb/BqX/duWXQFntD1m4qmkjAsXAwCDos
vX5J1u50ZngUzStrR736DnExBTdnR9ZuMpxaI/+YnRB5TKCFWF4iX3mftZsKh/wVWpt2lSyS
QUP5SPW9md3fZ3Y/pMMnGdTMGNjteTu0FXBgd+ftFO2AHti9+6v+4wS/v4HdnbdrFSRQA7s3
c+ffiYF57YFdQvBu2p9OcwZ75ptRelautXKvuJ35oszdjSbKVDThgdFLaZLZf1HgoUtr2gZv
M3dT0UQSzloLDdHGpWK6G75oScv+Xebu9GZ4uDdZX5PZSmKvYdx9mbs744y5aCIH1yu1VnrL
BTUUXGWccZe5m9wco2hOFb/plQYOZv9TM3ffosNH4GFGSzIBy+Y8tivxVbBad0C3NwGCzdsH
dDfjFAGVswd2694WSmjzygHdy+d61M6xT/eCbv10VVIGt/aAruCadNMCeLpG2DPXCN/VGL2P
vzpo3yNLGpnuR3enotHEGrOHIlaCQKOjuysGbtpdp/1kNFqFaxMhAesmumRA5Uav7s9z9vEs
FoqdCRHB7tdW1EeIluwM57uk9WQ00ll6Ub9DsoDuyLFoyd7c6DxORuOXTGea/kWJbw9KNOee
tN9ONP9N6nuKzr0N7F5mp6l1dLzjwO7mdq2ihm0Hduv+Vg6ZMlRgmVY4tz/hdiV1RbvsDuze
3c0tSQEN5U7wkmzi9clbTueI8kTO3+lNbZpr15K1oJLqq4Y8rsd256KR1Iv/kqJgTIb6gvmi
FWO7r6vSxck7F00UGZh7L9Ybo7fsskT9+sY44s+T9vEsmnBtZcm9mdNVhl095qxe/ys3ep23
no1GuFELH4wsGfaPmZMz+a+uxuu89Vw0/ob361ZYrWujCvbPxqI3x1vD8bZr70kFdbQHdje5
87cpTO4Cu53cGXr6H9i9iTtLWcDPN7B7k2M1+UkAau8d2K2fr8fYC/hOH9gl5O66Q6ucFg3l
oeGE1db8lHKqVcC0iixp0CLT67TKXDSarFEO04lChA4S6BKTM2p8nVaZi8aShbCb70sJ1Wss
zR6LlpC7667Tclo0PIomp87Kor2qlpASBIurK3pUbpWV58KhlD2SaFF5CRLDQ69LJnAueyy+
pqMR4a61eigGtzi9pffWsbsfk94DSdTA7u4HNANL7AO7l+TV5Jc78MdyYLfub4vvBOz3HNjd
/XYdtoU6sHv3VyQxg1/gCV5Spb3uCCynR0N5opzvX576fZ+Ea1YFXQ10Ujn/v3J417K3c9E4
n861ZHWux5Y7OiRRF3QfHJrBV2fvVDQ1lbB865V8ixisnvmiJR2B7XpqvJweDY+iCR30MOZV
1pwF3BtaIn59Q1o/J6Nx+knFornBqkcEalauIq31huZNbk6oIUo0nrLA3ZpznSdvlvfD0nuo
s9fA7mV2nPxnBbbdHdi9J78lv3rjo7yO3bq/kpOh6aeB3fr9ORcqho4aH9i9n8/3DLzlHtAl
ybur17mftac1Q3km/9+tmLXeyYkn2Hvni1ZEo5fy/5+T0USxiP2KVPwaZ2bfW2H6z8psvjlq
J6Ph2plUsrP5Ao8lr7jBMl16vP150j6eRRMzDr2asyDpUhkUA/JVa9rvrgd5Z8NpJKWXEvJG
vj9oOCv6l2/GrL/mwylRk6X2uuIx1tQwO2b9Jna/QIGPU1aw925gd5dnGdUKGtjd5VlGHWYG
di+/iz8T9RQ4sHv5k+8ZXC08sFs/n/b0Eq7HZo4cuoTfXU9XltOUoTxUyucuvTk96USgR7sv
WhHNS93i6tCdjIay1eyBZKd3sJ4grcja1X5z5k5FIylTpyJFnBQZaLPoi9bkuW743enJ8Cia
4AJcS+YcVhPSv5dBPOF3s+GQtp79t6MeDu3ldzdCLXPhUKLSnHhroV4Y7MmmSXOWN737WQk+
BaXaD+jurF00oqBZu8DuztpZAxvUB3Z31q6inhQv6PacXQGN7gZ2e86ugGImA7uC1ZWbCtlp
zFCeieX3yKBEv52WDCqA0JoJBMs3fVBT0ThBKzlrZRY/o+Ck3YoUpLPi64N2MhhuTasRRRoF
1P8IOcUVtOGvH7SPZ9HEK4TC0Y1KqVHx+zVJu8lwYtC8MWdyAgxWL3fk7Gaj8R9/TDNXf+SK
vHN2O0ndD+XsSAqcswvs7pxdBWtIB3R3xs5vQPBARWD3cruaioGfb2B3szt/04Cf78Bu/XwW
DAfrcF/Ehe6ElcvpylCeOWZwiGb7TyNzEdQzepGwst6ct5PRZOf4VWvJraFFJV+0xuD2Jocy
FY2klxlDN78XlEzooMsSg9vbYYrTlOFRNM4D/AVHoR8Smk8os2tLiOods5uNJmtm6516ZlWY
Cy0ZprhsgfyaDIcSi+8KcRXKHdRXp8m0/W9ndvz/XnfvEUkB+cmCV+QCHvxDaoDWDJYDDOxe
FhzGIaAg08Du5sGKWiy+oFt3l7UmYQK/vgHeyzNragry4IHdu79i/lCB18QTvCTPeaPmcVpZ
lEf2Apayv4CFRalVMKBYs4IN841uzFQ0kiwq1z3GZwx1+YlFK9hwvhktnoqmJeaYxmVyqqJg
Z0FbM6VBdNMHexpZPIpGU2+1Bq/v/jc4QeOLlrDhy2rv52Q0Ue0tzuyJqZB1tKt3yU3l1fN+
/6Q9jIZTWKYUf41Wpg7fiecktX87Gf43aQNKBiuxA7uX5VnqhPYnHti9LKAm/yPBM/PAbud5
DA/wDPDWb7CEKBH4AQd26+frnKyCE0YDu4TlXZ1WfvaefhblkcmAOgPVXDo7VWZwzuG1aEnS
86acPRWOMzbuUk1I2dk1TPNWtFw2vjl8p6Lx2wFxDocvloKKc8eiJTTvph329LN4FI0zNmfg
hf2noNLRNqlVAjI3NG8qGkqcM5loWONlsNcgFq2Ipt6UsyejaZrFr0hijFpKxpo3y1vD8var
A4K1zgO6m9xZA4dPB3Z3Cq/6lQjN4QV2L7kr7K8ZcH9P8NZvsPp7ENUtekG3p/BqeZDCC/AS
cndt7lFOA4nySNjfUmn6YnZmFTyiYs2SVsUbdcCpaF5zSLkQGzci0EguFq3gdnRT0J6KpiVy
jmXOVTUqjWgKj5ak8PimV/G0kHgUjaTKtVXq3KN3ApXlXuO8didQNBUNRebbpLfcOqGp7yWZ
b6d2N5eIyWC6ZDbqIlYN1rGe8wN4c7tfpA2YQQWZgd1L8kpqBNbxBnZ3Bs8vqXAGL7CbSZ4T
8wa6Qp3gvRm8gmvIDOzeHc5R/r8ycPlfAAAA///sXUuyJDeOPNHQCJIgiAuU2bx3irFezWK6
FzP3twEyImohWbA9WHh8pe5UyWRaOKVEMjLoxMf9j1t8gkNo3n03mVwuEvLIqaD5K16LUbxs
nxHUbGuLr/g/lWrvhWTWwqlplFIruS9GziiVGBEUXCaJlbVg2L7lUrjn3kULWLLgkK0xmnff
EyCXi8TDrenixseVhEcBx4xryIViqg64Fk1O2qjVoWo3JFZQKDSHyGpObdzWwnEbNyIqI7Pa
fx0VgV4Tx3oTve+VB2zou+TE7iV3JYmgTXgHdu/Rz8kt6dF8iGO37q+2VBW8d57Yrd9fzcmO
AHDU+MDubRIcqaCj0Cc2gti1+8YouRwk5JmDhAobbSisWSuYwLNFIfm7Njlul6KhpFTFZyZb
awo3RmlMC969QOBaNM5qXCfZmF3NuBFdD7GAvR2v+fmk/XgWjcsdug5lN/rQB9jXECR3WGbE
bimanKSoMbrM3I3eDdSrJCgdee8SuBaOneB+fSi5lUYVlFCgxTaAN7H7DeQBfUQSlQc8sLsr
tHmA16UTu7tCWwfaxXBg9/I7dzEFm9tO7F5+55LioCTaC7r107Wa3F8U+3Uc2JC03b2ph1zG
EfJEzd8uFrU1O2xJc89gPZNDDqk5u1uKxolaK6KtSha08y6I3Um9L5qtRVNSby7XRi4B3cC9
8UUh7O6+D0Au34iH0ZQ6upC78vZeYDHriGhKvx/lWYvGFW58NJeMf2dGGwltVUDLasm3KqGf
i+FQyrW0wj6KWAlWgc/v+uyvs7v96oCo6e2J3Z22s9MIdvVw7Pa0HYMlzxO7l9Zxqqg0xYnd
TesKehk+sXvTdppqA23jT2wIsbsjD3bcXt4R8kTPv6fclIcW5Zy1Ymk7WxQzUnHfDLUWjXG0
4Qa2jey07R1O2wUkumiUST12KZqaXErPLfqkCoOnrS0K0ZG59Vz5+aT9eBaNKxaJsQYjq4Lr
HUYIFpUXU5k/aA+DcYbWODe7jnvijvbyulnWbikc1/fNvRO59VxFbUZt0ZvX/Tqv+yaBwEqg
dsaJ3Z21awK2tJ3Y3Vm7NtCq7IHdTe+4g7/jE7uX3rk9AXi9OLF783bsF3fw+nNgQ+jdvdmC
XNYR8kTO/9UQUEd2MREVUMyHQ9TOjN7dkdWPxWhKytmt470FisGcua+JSNvdatZ8Lgfj7WlN
GhMoI1JiqN20InuZRjwMpbDtSGvViN1AO6VDpl2mEoFr0RhLG7m1PkSK/XBAFX1fFRHOuEuo
fi6GQykP13cZoxjzRmcBbdG/IrerXyERCKYBQjIAYZMe26X47JIEnqcHdi/fbMYxULuRA7u9
SoxKBZ7YrftL0pK39YMzKAd46zfYSxpon92J3bvDJMZU0JG3ExzCOSeJnsvZQh6ZjuTUWdm4
TbN/oCMetihi+JXzhA4shVOTBdJyMUqgrOD5WRf1Jv40yjspFi9FI4mMOlOprqPTCSOeEmKi
YsRzMk10OVs83BumSnb578q5D7SxMUIpsdDt3nwsRkPGiCVX1eojHvBQRIlR45vUipeiKXYK
DducStm/K/SKsybv8Lvzzn8rNT4G63Yndi/R60nBaYADupvmaQHTTid26+6W6uPD4E/5wO6t
yrbEAo7JntjNXQEvO3hUoPgAh5C8e4E0uTwu5JHxgF+CemPX4CIuYERtsRXoT5nFuzzpx2I4
NRU7Aon7GDoayMJriEixkbxJymcpmpHUrle2P1RfnVqgXktEf2PJeq/XIpfHxaNoWhJq2kv2
BscGDvL6oi9Nx30sRuOZtSpUymCyhw28HS2m4/5I8vLkOrEUTUmqbWSl0d3/GByjXGy4eJO8
30CMr6BpvBO7m9155h6ld47dze8G45Yajt3L77gn0ozqGR7grd+gkCeXYD0+x+7dYTFaqWBF
4AJHMDyZHLuXb4M89NQgFc5VendpMbSVNUI1dqrItxZOS4Wztmw0byjauemLQloDJxO9a5vj
V2cpzNwFrVv4mpg03kSq5TJueBRNTW7aQK2ruvgj2PVrP+6Q+vGkN3ApGiNrJXNnElKfgUUZ
Xox29CSNtxRN8eYluxex9wcPeLqovRleFMP7Jkk+RQ2ET+xeoifJTjyQpxzYzTQgNQb7K0/s
ZqI3ksvTgkTvAO+t11KqAuaVTuxmKs8Jvr4f2BCaNzl7L98GeWiqIUNaIXfgzQ021ZCImYmZ
d9paOF7c69LUngduFe0wTSGiOuM2ms/FaDRxds14NW4kAk7naFB9c0bzLuOGh3vTq2itI3PN
HbwG15hB5VwnKeOlaLL3iNgNrhcSu1WAj5qtiijXlplG0FI4JdnGsDa/HlFmuFz7ttX49RGQ
7Yp8FdSAOqB7mV21/yXqqHFgN5fw7C0GDha+oFv3ttvLv4EX6BO79dur3vUNlglO7N4CMnlK
EywgH9gQVjfpyL8cG+SZ/0Rrg6RqH92NKMBsV4xT2q3CycdiNMWuH9XCGMqtdEVnRyOURGnU
u0zk52I01a6jzUctu0slojPuMW1eVCbKQJdlw6NoKHV3OCnGUqUPwc4VipJZnjR7LkWTk4iq
/XCKtkxo6Txo9uO+o/BzeXNKtWdN3ZPP3gdgPmJRTOdN6n4DNb6SiMBXyondXqCtoOzIid1d
oK0Emgmf2K37q8UNeDF+cmL37q8mVXQA8MDuzSrWNCo6BXJgI/jdbb/af5ZxWTWMZ1YN3nun
2Uf6VEEPKw6pmNkjf++isRYN2RdtPFWkez4FzD2sWnr+cbD3tl/tczGa6m3DLNXIt1IF74o1
pvuObn19fz5pP55FYy+RYZeIxsP+oJO9FKEc/fqdzp+zh7EYT6NiP0b1c8+4N5a9z0GthJMm
gLVwKDFxdxbMnZui7G7tlfZmd9+rxtcL2ElwYncn7RqDtOTEbk/aNZB2ntjd5XbKYNrpxO5O
29WM9uUc2N1pO/DTvZAhKbt74dtxmTSMJ8r5zUU0+9DBRXJuaJt7hBfiNGW3Fo1n37j13l5j
wGD3oC0KSHJNU3Zr0VR7pDt3IbuQZtSNxxbFULr7lN24PBoeRePZt0as2kQKKUq3vzxltxaN
p+zs3sCZ7UbU0crWhpTd6ua4wHJvlexqx2Cp5J2y+0tL8RVQ5vyAbk/YNVD04MTuTtg1QUfl
D+zehJ3rsYIJxRO7l9mR7Rkss5w3m3t078wCnaFP7Fen6y6LhvHMPqOrnRWqmkVQVyQOMeAi
bvc9dmvRUBqjlVqVjERIQVWWIyST5um6pWhqGsxqN2Y7c7OAD5stihml+KdP2o9n0fgJYVFw
Lll5gLrEJWSQueR+Pyy7Fo3bnDF5RKO4TyycsItpGZxwu6VwKLlkdLfd6S9FPjRhtzRR9btz
uy+R4qMCfqkRboB/ZTE+2NvjwG5vAQTLJgd0e4m4gLm6E7t1d8m2jBkcTDiwezmdppbBGfIT
u/XzSbezHZRoObERnPM2Z2VM4HKPGE80/TWRfTTiXEeTAT4QGqL0Nh3fXYvGJ3GLsU0v3XXJ
4H05aHx34rewGo0YPSvN7lNaFY4mpg6pkxLx5R7xKJqaMmWSLr2pve6wnjlfFELS7vbmYzEa
co/y7Nlr7QPVqHfb25Aa8f0E0Wo03ISyjmzHeEY7m+xQ+FeknP9WKnwVzNqd2L0Mr6UhaJvY
gd3N8ZTQevGB3cvxpCV74eIqIw7ey/JcaBa84Z7YvTtMnGBt/wscUje+18Adl4/EeKTvn1NR
LaVzd6cPMBuXQ5y1iOskubgUTk1q51XTxkKCGov7opDk4l2p9XMxGrsfZPbWe1cCGeDkii2K
KRzfK3uPy0ri4d60nslYXu/U0G5AXxRC9CZdp0vRkNtt2w9Su/2dweFqXxSyN3dl8M/FaEoq
o7emQ3NtaEnHPfneRC+G6G3vGKtoR+CJ3c3wBLU1ekF387sh6NXuwG7O4fXU4dvaCd6bJZPU
FFSqPrFbP59qInB674CGcLtJp9bl1jCeaOiP1I00CJPklgtIp0dM3bjdkqGPxWhc7LDaX67M
Ao8kc0Qsctut+bkYC9tLoRfmzGVQzlh2lUNq4EYe7tW8x+XV8CiakvJorpjT7Sor4B2ixIgS
U727EX0sRkOJcjGeqm4jhQ4kU0j+bpYpXoylZR3kJtBsVwm016ItXSDetO73kd8TVIbixO7u
CuQODhyd2L38zhjHQAeiDuzW/S25pYYaVVzgvfk7thcP2nl3YPfucCN77EGdoAscwvEm1bPL
rGE8MgQg42t2pA8pygRqbr4WReTveFKoXQqnppfqTKmFRq+MFgMjOrZo0CSrshTNMF7ghc3e
dHAHh3JsUUj+btYScLk1PIqmGP98dW5ya00Ii8YWRUzz5hnNW4omJ3XPlt67kN2RQFsiXxWy
OZNp3sXNydmuRUbC2+CMmhgsulu/md73CvA11DLpxO5ldyX1gmoDH9i9Z78LWaDJsQO7t/ou
yU8MLCVwYLd+f9WOW0LlVw/s3s/XkwyQOLygIbxu0ol/WTSMh6YGw0hd5iEyGti6XqNyd5Ni
2VI0JZGdsEYdiO3IBfMQvigie3frG/u5HE1tyi2LUyHUotgNTUOI0ITWXRYNj6LxjrXKvXPn
YfcTuJAZQ+sm87xL0bxMD+0+6TujzLiucgTnrjxJ4K2GM6SyNup1jAw2NORF0v3mdb+BBh8l
HQUWa3Hs7tIsSD5fyN2F2dLB4YATu3Vvu6b+aqDGhhccu5c6tVQ7qG93Yrd+PnYnS4WlWhwb
Qe54krS7jBnGE7V8+2GIW86777ytxI5cWxQxddbGRKxlKRoXAi1SpBrTr7D9X0iWi8asE2op
mpqo2YPTB1Pu8D0nRTjwzMVaLl+GR9G4h+GwS0Sto3FD6389puVuwu2WgnGWNpgH9cZSFOxS
s1Ux3miT0fHFvSnkGo9dqnRUv4sWz9Q3tfteAb5aUdPIA7s7ZSegkNMB3Z6wy+CxcmL3JuxG
IlRE5sTuTtgpg+MyJ3bv5xOXJARZ54GNYHU0keC7nBnGM2cGO5SyHbNZsxZwLNMLnhGV2Nva
5cdiNMWnfkSE7cgtuARfRKsrjVvq8LkcTZVB3FVyrbZBaMouRrTu3gptXMYMj6Lxti6pzahQ
y1UqOK2/2Nb1p2gmMi1L0ThBswd4GMPy5LCgldgYWndbWP5cD0f9V/NqvdVXHyxWWH6XYgN4
3Tdp8FXUwe/E7k7ZyUArsgd2d9qugcflAd3bTVnTeL0lkG7KA7ub3tmrBqZ3jt2btHM3sQLW
sw9sSEX2nt7pZcygT/Ty7aPpKMOO2+6zmNhrvS3Kb/1pUPY+abcWzUtheWS3MmilgN5OGxSW
16JxseQjkNqHgipetiiml+ue3unlzPAoGkrSjN1l5kwiYO2fomTr7i8Sa9EYH8ruDl1KVguK
UBW+ETJSIfeSKKubU0bPQ7gIi4L5YfqLTsru427/84+//+P//vH3//7bf/zX//5t6/kEjsVt
ZkQgGwp4GwfQ7u+QIaxuLoyKCBzYvaTbjUrGA1OTiOG+Z6SbUSG9E7s3q+pGNKjW8YHdvb+l
gSMuJ3bva234XDx2PJ3YgJcJjfvhUr3MM/SZeYZ3V6oYc2ijgTobtigmqzqh3UvReObOLhFZ
CnOvsKVqROaOxq272+diNJyqqF2H3LnXHYnBMeaQrCrdEtWfT9qPp3vTG2sfo7rKIZxVjXBF
LLnfT1KtReMy1pTVM6suMAa+qYLEr8u4z6quhVPScF8oriN3QT1qfdFfkXb/XknVb1QiNOI2
0EnmE7uXBLBPhoLDVgd2L8mTRGC35gHdS/FKKqid84ndTfGkoq+aA7uX4tlRWsF20hMbQfFu
h37t4L08NPSZh0b2ZJfROx/WQEddcogb8W3H/sdiMHbVHL3ZqVstnAEn7yLGKWjc1mY/F6Np
SUd7WYKUllFdOF8UwvAmKfzLQePh3vQqw9u+XdocfTGmiG4sY3j/9El7GI1ztVZ5DHe9VoHr
5iEMr97qgH8uhlNSF3cVrG6WCDs4LPoKvhned0sQ1pZyRis1B3Y3tevoLMSJ3Z2/kwHOg53Y
veROXNganWLWiGmAZxJEAupxHNCtn06rS21gv40TG0Hsbs3R7Ly9jCr0mbWDVzGrESIpOcNq
Li2G2U0KmUvRkAsQinYSIRfbAdlDiAThmLSprUXD9sGaZ9G8mKmgtjSHRDOdc9HLqOLh3kiu
VJqrn0gD72y+6KtL5kvRuL1w72K3Im3G7kCxCldyC8nd3cuYr4VTknTyUry9AwqDqlu+6M3s
gpjdt+TuWhIBsxMndjcFGIw2Ph3Y3bm7RqDI34ndS/CG3abB3OeJ3bu/knoBC9wndi/Jy/ad
gJ/vxIaQvEm32mVSoc9sHXyC0baXmmZG3aBTjegkZL4fRliLxvja6K2SEVf1lsKdJE9uB80/
F6PhVLKxoZ6NFGkDtV180VeTvMuk4uHe9NGNQ/AwWlTB61uM1OWc5C1F43TNHrTcWAa3Dg44
BpG8dmux+LkYTkk9++hl79pyRQes+ltp+pc53mb9wTISbBDzgu499T2NjArUHNi9rI6N6YL2
BSd2L2s3pqECHuIHdjcrZkbbYw/s1s/X7DtB21NObABzKHJv1qWXQ4U+cw4wvuDUQd2ADPTi
sUUxqbu7ZNfHcjRERatPl/aGOrtQkERNneRTlqIpiYVtW1ywb4yC6g9G3B9KHpOi7OVR8XBv
sj1qo3Ojbn9QjZocQYPqrcndx2I02S+Smo1fETX7G53+7SG+cPRPH7XHm9PaaCJl+MQ5bIey
lsF/07rvlx80ytYZlB88sbvLsrmDZc8Tu7ssW+C0wYHd3VFp7ydQ1ezA7uZ3A/XleEG3frqq
Lw8E7Ns7sCE5u8mZexlT6CPXkKSkowi36jp3KB8KkVNkvneGW40m6/AMpAh3Qj2MQzy7jN1N
cnZL0RQ7clVGL3Y11QZ6w5WQovmc3V2+FI/3JqsoF6FeYZvcEHZX2r299Fo0zu6MpnZpXiYl
cDzNV4WkICc5u8XNqVpeztK1aAabnVZ7Vd/s7hsVCI2q+cQZSuscuzttN9BuwBO7PW3XG6xB
6NjdabvawGL2id2ftoNpXYjlyrOknV1uQQGnA/vVtO4yptBnVg5aWpdRXQOloA7VUbRuMiu7
GA1R5UI9c28V1OwLS9rdGbp8Lkbj+TdjDUZRa5cCan5HJe14MpV9+VI83BtPB9FQZZICSttS
iHyQ0bpJ0m4pmvxyoWKporkPsHoUxOqmObvFvWmNjHH3PDoPsAfbF71Z3a+zum/J2WnK6ID3
id2ds2ugv+IB3Z2xa7CO04HdnbFD2wAP6N5vz0v8AjKNA7s7Y6cVdXE4sCH12MmBe9lS6DOz
AJ/za3ZVp2oUDyyAh5ivzjN2i9FkrerGdpwHPMUUkhUyanfvvboWTUmt5FFUbXs6dXRyMaIz
Zk7tLluKp3sjVGsufbi2C1yP/XJqtxSNs7SsnFsZOSv6It2RsVvcHHtB5UG12wZVWKNm7Uj9
3bldhbndE+t67KyImAn/C0vvFbDKckD3ss2aHoh27NbsMAZZH9SH6+76MHsvO/j1ndjdu8sd
l1V07NbPp8U4LlghPrERqcSZ7N5lmKHPzEyoGZkhdx82qoYl32qMYy/zXfLtYzEaslvl6J3H
4OqWGV+aEnkyursUDXvbqFQh5wEMRsNB6arZVMfll/FwbywGLrVJHbmANaAg2T2a3WyWoslJ
mMvQQr0JCWE/nLw47PrHdsb8Tx+1h+GUpE1FO2e3zoG9HdfagH93vvnvJLunBTxkT+xeEtCT
FHBI4cTuJnkKy0sd2L0kz829wKTdid1N8hqq7X1i95I8u9U0sPnnxEaQvHvhvZpP2wz/lyck
L4to7TK6veJRw7oIjU0jl7dyaIvBuPCeO4Aw2VH1oilYaiTEsO5eWnkxGldJLqzuVSe5gQ27
YdLKt40JVzQ/nu5Nr4201CJaFC4XhwxF5H47I74YjXeA2KXIOGseY9jpgnK8iHAm0sqL4ZQ0
WIYXov27Ap2ubNFbniWI420X3oMnFE7sbnKXGzjheWJ3k7sB2xEf2L3kTtJAJ6BP7O79HRns
BTyxe8md4sYeJzakGXBC7uhiEM+MM1prXckInstugfn6mJwX820dbzEaTzUzG7uzYzcT2kqa
esSMh9x6CX4uRsNJs5RhZIgEnnm1RREGvpMM3hXNj6d708egXIwUDUVrL1+vy7IYjYvveWOj
cK5ZSWF2F0O9byvGi+EYUdPm0152N2JChTsWG0fe7O73Ed8baNPYC7qXAkgqil40Duxeiiep
ZdSc6cDupXjDTkOwvf/Ebqd4DOYXT+xuincMbmIUz7EhFO9Weq/mctGIZ8YZtUuWqlRZUSeV
MOm92+HKxWiM4rXafCjZpXwHmsCLuB6Q3JacPxejYeM36lLEXkVvqBJ6jCLxlOKVi0U8dM4Y
rmSjpbsFNiy9FzK9MqN4S9Fk19XSVycAN7tPwEXakB7HWQJvKRxja3bR09Y7ZWPhaP/peBdp
f33gY7v2Xnkgvle+RX2vgbm7A7uX2HEaHVS3ObF7abu9YzJqanxg935/I1FH5VkO7NbP1yhJ
BzXHT2wEsbut/tlxWy/y8MzOQCtLsWOAmr3WYfW9kNzdvRXpcjTUuPYs7s0gHW1aD+klHPWO
pn4uRmOvrVqNYomxulHBPugSVMu812e5ovnxdG/yGH0MuyJ2oY4SuxB9liyTHoClaHLqPvta
2VhqLgIKG+Ugh7d7KaDlzWnD6/9KeozGYF2rb0e0AF73TeJ7gra1vaDbC7MVJZ8HdndhtsLk
7sDu7qq0/yVI7g7sbnKnDGZlT+xecldSLmDl78QGEAg7SO6P3HYRiGc2BlrLYM2DsjDB4nsB
BMLI3eTIXYyGeNTqsv+dBRZ4i2jaoNEm1bKlaIpPDNXhxiKZq6LVMo5IDNHtoMjPJ+3H073J
qnaFYE9AZrCJMEYYsVS6HeJZjMZoGvsMfLffJI1MaGE24jVaiCZZu8XNaT33yrWqzyXDMi3v
trtfZ3f7xfcGKNlwYndn7exqDovvOXZ31k44g20lB3Z31g6cxH8h92fs0G7FA7s9YycE+mUc
2JBS7CSPwhdxeOiXUVorOWepvYHzslHSezNStxgNsSuA9DKKa8PuzNjJrXHv52I0xWXqyd2p
OOcKlmJLzITpRJ/liubH073JQk1bKbWTgPfxIH2WV4/B/El7GI3n3sgIEDejQSMLTOq+PGO3
uDlNeu9ETGPAs8zvjF0Ep/u2jB1O7Ry7PWfX8ElZx+7O2TUBqeeJ3Z2zQ+0RDujeb0/tyEWv
9Qd2d8auEGgRfGIjMnb34ns194tAPNPJH0NENdvVIndFX+sx4nt90v20GA0ZrxtUvTyfwW6N
oIyd3BrVfS5G4xm70jrZqjE62nuSIhon5uXYfvGHh3YZw/64gxi7ljdK7iL67Oq9mfJiNJ57
Y/Gavxa7FIGNI7YqJJ06y9gtbk7rkrv32bWMi++1t/ge/A2jlDnC/uGvLL+Henmc2L2cs7r/
Baze4djtdeKCenkc2K3767J6oLjIAd29u5VwbRbHbv18ajzygQBf+XIBvprl4jVPVPxdS2+4
MlCrpYug47shLI1nkhlL0dgpWEbpRtE8LQKnR1tEzXs627EUDafOWZm0aSkKztlxkGTd7TTE
zyftx9O9cW42spsC2S6htCYmPTpLXS9Fk5MYde5svxwVe9ZQMw+JCGciwLcYjmvpkWdIM1tI
cEPCW4AvjNt9kwCfXQJhAT7H7iUBksCm9BdyN70bHZyFPLF76V1JNEACdWL37m1LpaIO0Ad2
N8HrAn5/JzakDXAyvDsuEvFEyr+6771W6VmFOkzwQjwwJgrLi9E4VxNqQkVKzqAkWpDCsty2
aH4uRsOpaS/sXiH2L7D6HocM787U98bFIZ7tTW/ZWHBt3RhegwleTIl1kr5eisa1ku26ZRc3
zjQa+CaIUljWyV1iKRzjalRFmVVy0QaeqotSQG+C9xuo75GAavov6O5ysdEhuFzs2N3cThTX
3nPsXm4nacDCLAd29/42cP7ygO5ldupsDXv6TmxIL+BkwEMv9vDMO6M1UcpCeYwCnre2KMQ7
o99lID4Wo6HEwtpzluI9Z+gQQcSNlEQmx+1SNJy09lZ1SG65gMM3HDJZPZdl0Ys8PPTOsBvE
KFJLHl1RyZyvV95bisYFVhp5hlhtg9Bh5CBZlimzWwrHSVovxupKaxks6JTFjuA3sft9hPd0
ZLA4e2D3MoDh/r9ww2LeXpyV1NAh4xO7l+GN1CvIQE/s9swsaj1yYndzPBnYqXtAQxjefe6O
LncGemacUXtRrkVYGurA5YtCcnf3xdm1aJys9Ty0UW5dM9reyBGZSLl14PpcjIaTGEvNLKSu
r4wyvIjG5ynDo8uc4eHedLG9qZWaMMHaOV8uvLcWTfYrOWfKJXPnDmo8+qqAcGbCe2vhuIZe
YaeOuRlnhbWV38XZXx/32C68l2FhuwO7uyuLBjgie2L30jp2jUpceK9FDO0/G+HtA7yjndi9
399ITQUe43Xs1s/XyB0N0ClejRhGnMru0WXLQM+MDDw5pER5cC7gLGKY7N6tFelyNNSlyJDB
lRvDQ7wReyOTycq1aIpLu3ErRlFdBAQe4g0pYk7mPOhyZXi4N1ntatiUbXsGbEgcIrs3U2ZZ
i+alzDJ6z0aA7UYOnkNByiyzId7VzWlaJJPtjVIp8JzH2zIjgNZ90xRvL6jl2IHdXbYbFZyj
PLG7y7K14lO8jt3dTlkULMO9oLu5Hbi3L+ReXldSQ5VHT2xIs919jztdbgz0zL/AJSZG925F
Jdi/4MvlWVajsWCY1P3QGsF2qjGCyu0ums/FaEry3icjd0W0K2jcW0Ks3ebM7jJjeLg3xuyK
59W7/0GTqV/P7JaieTE7bWVoL9KowYLKX87sFjenDdsY90FrWRUVq3zrswQwu+2aexW1iTyx
uxN2hVHNvQO7O2EnAlp4ndjdCbtK4Jjnid2fsANvji/o9nQdgzMeJzakDjs5bC8vBnrok2EU
aPRcWCuDjZdhtO5eC201GhLSbotcAwR0pYpK2E1U99aiKS/q0O0umrudt2j/UwxzmKju0WXF
8HBvsjvtuVFGyQ2ukceo7rUJrVuKxmldNXo1eq3V7kTYiyoHzfzOaN3i5rRB3btF+9ABtte/
ad1fWHZPU0abnF7Q3ek6BVMMB3R3so5hc9sDuztZRxmULDyxu5mdNyej1M6xu1N2PEB5mxMb
wu3ummvsxL2sGOiZPv4YTKXZG71phaXQgkT3JifuYjTkfvKl6rBvHPQeDkvZTbjdUjT+2GSj
ENKLEIHtsCVkJmTO7S4nhod7k8W+JM9z0UCn83Zwu6VonKW13EicdZcKT1HEqNNMRPdWN6d1
sSWNySW80R/Ov6boXvkK0T2wb7HuHvUEGUrACzKAB3+TEGBF5X9P7O4cZ0MNu07sdiZccMM4
x27dXyqcqKLlvRO8e4ergn67J3br51PXnQNFs05sSPl6kue8HCzoia2AJJbaOffas6LkXkJs
yeilRXnHUJaisS+aenEtaGMqHc2Sp4hJLxplQlCWouHE3tDSjNwLlY6Vr31RBN2qk3mTy8Di
UTQ1qeZ66E7akwZK39uiCGY/a5RYisbFAN0kxeXzFJ7QiBIDnEwUr4XjE8XMRaS4GuB4jxRv
53ffJQbI4B37xO4lAZwGgRezE7uX5old1UEaemK30zy32oJpnoP37nBLaI7HkVs/25CEWnod
0BCCN0l2Xi4W9MRawD6ZUbtemr3YOziqYWtCBk8mnl5rwRhVyzLEZ1aHcSLYBStia17KkHeH
7lI0dq2iWnqp3LJLCoP8LuJBK1knuc7Lw+JRNNXNp5XZVpERVnDiLcR8utDtrPfHYjTO1Jq4
Iamb8wyCFWMi+F0Zk9H1pXCK0VV/uRSuY3RY7Hlt1u/N734DLcCs4GX+xO4mdm6GjhI7x+7O
3wmh9mcHdi+xq5Lw9vwTvHeHje4qqvd4YPfm7zRltE/xxEbQuzzJqlyGEfRExX+4t52KUlNF
ZdpsTUyb4h2F+FgMhlIvub+sIppWuJQd8ehMBQHXouGXcTMR9epNl9hvgUNaSAvddsL9fNB+
PIvGTonqE9LVncoEzMz7opC+volczFI0LvzSpOU22Oc1QLYaJBczTd8thVOS2huqcav2A8qo
gcJb6jmO3n2TIqCAJOqA7u5VRLP8B3R36q4q2qt4YLczPMloCfkE793fYawIrdAe2L0Mr9vh
g2o+H9iQBN6E4V2OEfRExl/sNS2DWZlEC+h/IUGTKHKnYP2xGI2xNaqNBhU/qWCn0wi98HmF
dikaTlxI1SUb7flBxTtTxJNmFO+ORfx80n48i6Ym7W4/20ulQmC92Rd9NcVbiiankUWatjo6
cwZtcGxVRHp1msFbCqe4nSmzcOPMxODBuuhN8qZ436sISA1Njh3YvQd/8YQX9vFe0L3EjtOo
aIvngd26uyyJQCfMA7qbFnc0rfiCbv10jYzmgnf1ExtC6Sa5lMsqgp7ZeHQyNtJVhnJtoGlP
DAni2zLmx2I0lMiIYrNFQqhPBIV03NW7BOTnYigl9dpa59K6FAIpgy8K4XN33ZA/H7MfT6Mx
gu2KhtRcBBJt6gpJ2RFNtMSXosmpF+nVHc1yVgXlt3PM5kwni5fCeU0W26+/GuceDJ6n78ni
v7YU4ANa17fTOk5ZUTGFA7u7JmtXbLCX7cDuJXY9UQblG07s3u9vpIx6Wp7YveQuG2EDM7In
NoBDzDzayuUSUZ45eBgVItVu/IRrQcldRP7baNh9n/taND4GX7sWtRN9CKP5OgqQ0KNX+eDm
0F2Lptj5+ZLzcfHdDAsCrunv/pFCyP01olwmEQ/3Rnlw79qMDjGq9BmTr6N8P128Fo0ztWx/
lazNQgLfBGH87l57cnVzmkeiUlstBayTrI4ivfndNwsCDlRD+cDuztcpoZ/vwG7P2MHunwd2
L7HzkTqs7HZAt2fsGph2eUG3Z+wYbOQ6sSFtdvelsXJ5RJQnwv01cdaRSevQnMG+Rlv01Rm7
tWheGTt6tdpRVlwyJiRp1+6LsGvReP5tSGlaepWGvuiC/DtmpO6yiHi4N8ou1NiMOnTOaEI1
hNS99NjnT9qTaP4fAAD//+x9y5ItOW7kFw0HJACCNNP6minzMzSz0ELqxcz/m4ATjLvosojr
wWYyb1Wdlqxq4+xOHEYEnXi4j6RdDJZ6QEWLEpy0W1Ihv5GMmd0ciaKCae1VX+0Ef2PJmL+J
HGA20KVgYHcn7QSsJh7Q3Sk7RdUUB3Z7yk5AS+CB3Z2yK6CywAHdnbBjA4dkBnYJt7suk5XT
JaI8ke7nJP7gFc1qTQ20wotFX52wm4omcm9hReCUiDPqF74sYXfd9TQXTUkSOi6UqXXVjDa2
r7jl3HO70yTi4d7ERAiF4E6pBDZHrxEV94/DDbebiiZYmpPu0qxVp90d25xF3I74Km//Ob05
3ISUau5U0L76WPRX5Hb8FXKAYGPRiovZn1h4z98nWJElsHv5JicWUEJ5YLcXiQVNth/Yrfsb
IiuhngorsgR49w7XjDoWHtitf193Hl5AzeaBXdIDeJNRPE0syhNnAYupdspOBbI5v8G4QCxa
wjqvm+3nosnO0yTX3pqz/Maw/dWKT73ZTZl4KhpNHgYXKc5rMjd0cretEKG+m9wtp4fFo2gk
UZYm4bVWnHRi0cSiFdHcCLPMRfMSZqm1+SvDMaSCss4lwixCN2XiqXA4kRWOXoROLYO+cTyp
EP67s86/lfBeRkd3D+xeEhCaJmAHxsDupnkdHbcb2M00ryZCS1EneDfN0wqOFw/sXpqniQjV
Vz6wS2jeTXLx9LMoT0wGLAlXLkStNidIWKre1hAj1Zvk4lQ0OXH3nzqycaVrQ2neCh+i3Pim
mjcVjd+uSDNTqUX8JcQ6NXXJGM7t9G457SweRRODuIWMyV9VRp0XFg3v1usx8blgQl6ZqlBT
7rUTLq+8oqjP9Msn7WE4JfVWJYsRKTdDWxTmtK/fLO83kN+DSy8Du5vekYIWtwO7m9455YXp
XWD30jsOfQ1UV3mAd++wEw6wb+HA7t1h4jBPBAnyAC+pHl/Ls5TTpKE8Uc5vqRCzdHNa5HQC
VuBbUz2+HrKciyYn7c3f99qdC2dQTzA7j1qRx6s3x+5UNJH+NQk14t46OP/qa5YMFNwljE+L
hkfByEuiKLdGjUtvWN5rjWj6rTrLXDRO1Vr1SPw/rRBqarpIgI/69TTvXDgcOVaqVTSGpMDy
BE/mWN8E7/cR4IuPJcrzAruXBVjy2y3IAg7sXhYQ2RF0JPXAbuZ5LamC17UTvJvndUHvkwd2
M88rSWGjhgFeksi7tjcop1lDeeaj0aW2Enah4QaPqvCtcNnVS1/aj8lgnOaJqkajIJhj9RUr
Qrmt1U6FEmVX321/sM0/X2BNZVmt9uY2cfo0PIqGk9Pv5rH43pSKS/AtsT++I3lT0ThdMynF
fF+cfkvBst+x6quzeFPhlPgEdPNjSMLTGU3iTb03b473zQp89YECX/0GBT50rmJg9576/n0V
7IJ6QLfursbXH8zODuzeX6+lImhx+8Bu/fuEk7MGcKb3wK5gdHdCLac/Q3kims9JSy1qzM7o
GOxZ4yX2qlnrjXzGVDQ5Zc0vvTen0YyaEvqiJZm7m7aoqWj8o8W55yzhJNbhuQ9bI8R3c3c4
7Rke7k1vYb+lteRecaGWJazuMqv6MRkNpepsW4VCX5kY1ATyVUuGcsq15uPs5ihb9msnkxLe
0zBn5fmmdb+FEJ+hSbEXdC+3U3/vwbvFC7q7MssVfEVe0L3MLv4nwbr2wO5mdmjh5oDu5nWV
wFn3gV3AHW4F+E5ThvLMxkAk5hG1FD+eKlqLWdNyd2M0PxeNU7TqUWTr2S9KYGUpFq1ouZOb
OtlUNCU0w50LOUmVDna7x5oVzOFunPe0ZHi4Nd0JnQfjfMgYvbEtkmq5bGT4mIzGCVqlXtgD
yq2WjlZk12zO5XTy5/TmaNjmUG6htArqsuZJa5Y3rftm/T1DhxUO7PZsXQUv5AO7O1vnLwrs
mBHY3fk6Q0VaXtD92TpQFvcF3c3puIK5zoH96lzdacxQnjlmaIgql94q5QIO/S3L1d1wuqlo
Iu2mGuVkk9bQRtc1nO42VzcVTdjE+03K6Xb1Y9zQutiSgcxbUnf6Mjzcm+50rigJESnMG5aQ
updv0f2T9jCayNWV7teHXvkl5I2SuiVdg3e5usnN0dLYd93YPBg4Vzf1GXiTut9Afy/SIKBA
6cDu7r8ixvvsA7s7X+d3U/AjdmB3Z+ykgSmagd37+3U/ddEWqQO7m98Z2sI1sF+cs+PTmIEf
mmaURuLMrknv4GVklWlGve57mosmqBrHUEjOYeuFcog1/E6vovmcjKakqtxKtLVrtOyjSbuv
5nd8+jI83JsurWft7N8SdBQzL2nkvE3azUUT6Td/wqjn1qoIOF++IWk3uznOuE1r9VtKjJij
/O4vOUbxJRp8Gax85hVlzz+zCh/qlziwe1knp0a4Rltgt1eJUau7gd26vy9hPUFp8QDv3mEW
VHf8wG79+17KeiBNG9gVecWboUo+vSP4iaB/COqZdfWLo/UGFhF80QpBE63X07tz0YR9VGNt
WSXXAusLL2HRd5Mdc9FE620WyyFkjQ7bbxDh49M54lEwoacXGskmVXIHCwa+aIn0s163AM5F
E0IrNW4DnWojVVie5atF+ObCCT09iSq+UnWSjlo2vkX4ltG7b5neLSmjdHhg93KAOGfQ3OKB
3c3y/NIJs7zAbmZ5Tjw6mFw8wXt3WFJp4Mk2sLtZXkhNoCwvsCtYHl0xCT98TxcJfiLtb0mM
qWehVk0KqrW8Yi4pq15PesxFE4StZfPjl7uwoNXjNVrLl3q+n5PRaDISETYyzTmjIny2QHHG
T/rrSQ8+TSQeRcOpl249O+dqncELnC9aMrdyo7U8F00QtlrMmoUvhoDjyL5qSTGcrptP58IJ
Qb1uXJx/U644zZt61N407zdQ4SsZTPAP7O7acc0Env4Hdju/Q0+XF3QvuwtZPVTv4QTv3l8B
S7MHdO/ukh87htL3AV7B7vLV7d3P3NOtgZ9I6Dcn7rnVmEikLAVV4Mtrcng3qZWpaHJSK9ZU
6yuFB6uzrOCqdwp8c9H4pSp6DhqJahdw9ikWfXUS7zRreBRNSPAV5dYyCVfQpikWreCqN+os
c9EMdZYsyqVZBu95i9RZ7iT45sLh6K6qnZWtlSYwu3vP8a5id98kwdcLSKIGdi8JaIlQpeUX
dC8JsORfAPCMObCbSV5L1cAv0wnen6QF/8CB3UzzIm+IlroHeEmp9ia1cro18DMnja49dN60
+L/AQVhb0pif9bKp7mMyGmdsrUdGMvshbKhYUtIVpNXqTRJvKpoQIlCPRkuJkUuwn3fS3+Cf
aZ7cNKOebg2Poom7TvYlMToR80ZoEm8JL7qjeVPRhGYyx1hvEev+jYRF+FZszp0I31w4h5VG
KK37vxQd+3xbaawYAdmvwkfYbf6A7u7Q8gsm+Pgd2L0Hv6YGy4Ad2K27q/75Bz+tB3Tvr9eS
ors7sFv/PuEkqIjRwK4gdXdzH6dDAz/TzVcmJ4u1OxsiMD+0bK73pl42FU1O2Uirley0TipK
6lZku27neueiible59old5ZIre6c632ZY94/aT+e7o0/YuS0IatzrA5O7K+hqJxvegCmogk1
va6SiWrnVsBHbdncx/Vc7+zmqL8uvYdcC1qSmBQkf1O630OBj8A5shd0d92uKahi8ILursqy
dLCp7cDu5XU1mtDBbu0Du5vZNQUnygd2N7MztOtzYBewh9uJ3tOXgZ85GfjtnJWkR9NYRp0M
ZIlhxo1iy1w0odjC/v/auVs2tCq7RF35JaV+ddxORVNStdZ6LqXWXsED1xct0SO+m+g9bRke
7k13MsTcnK6SgdqpeU26rlzmtz4mowlmV5vmQlRK6YYdkzuY3eTmaPHNyX63YymgONBbseXP
KcPn93i41BnY3Qm7Ar5NB3R3us6PSfDqc2B3p+sM7WYb2O0Ju4L+fgd2e8IOFDE8oF+drjtt
GfihZQa36BaSIpxBFs2TWvl/IHXX4mhz0UTmTRs1f9ctOu5QUreCcN+m66aiicybFaqRS9UM
Z+tW0IY7xww+TRkebk03ao2VxR8zeGuWcDq+5Nsfk9EEp5POIX1NRKIwp/tqx4zZzfGLkPVM
fq1jAtVF344Zf2IVvp6IwJzOwO7O2HW4Fntgd+fsBK4mHtjdOTslMOc0sHt/P3+m0I6vgd1N
7jqBc7wD+9U5u9OdgR86Z3CjYv5t78ZgjWyDc8ZcNJF+a7V5SCySUdeaVc4ZN9JoU9FEzi4X
a9yK/wtsGIxFX52zO90ZHu5Ndy5U/Gdq0iuajl+lwneTs5uK5pWz0yIWaihGoLrLDhW+yc2J
zH347vmXSkCnx7+qCl/506vwPSIqIEdZ8IlcwIa/SRuQGfydBnZ3mjPcr9A8Z2C3c+GewQLa
gd171zFNx4EHTXQc4L07LInRufaB3fr3Nd81BU+NgV2S7LyZKz59LfiR2UBNNRToWmPysxBu
uVgjDmg3JGUunCQm2sgJZKmotmReI4LzGuG64ihT0fh7J5GpE36Ne2J0OBatSHfKLx+1H8+i
acmJvVGY0IZYK/jupBWTWvcTJ1PRxIhwfaVti29RA3v4aU04pd0MN02FE4n17jevbCGuCcrG
zGbWf3c6/PdRB8ypZTBnN7B7WYD6W4bmZA/sXp5niWBrqwO7meeVGMFEed4B3r3DLYPVlYHd
+vdV/00KKBA0sEt43tVx9e8sp7+FPDId0NS1CpUw61DUEUIXTRbb9RDKZDhJMzVt0qVkMrR0
Ope9+ee0J13zvLloOAYdupJ25SxgNLwms5bll4/aj2fRtKTV1O8U/ZX3RKWKVoj73PK8uWjI
vzmhdGgeTxYuaNqzLXjUbnLSn5PhvPpIcy21kLLCyktzPQdvnvcbyANSB7VPBnb38V8Z/PsG
dncizxpalD2wm5sW/EbJKH8a4L073FOoqsJtFXVzWbvZi0pgh9SBXULwruWf5TSSkEe2GJY4
iqZUW6sEyra9Fi0heNdti5Ph+JPqxxQTqxA4WBNrvjiPNxeMJifdFmbI/gEj8NCNRUv43S+f
tB/PoonGYguPj5a1N3BMqC0ZZ/cf77ptcS4aZ2pa1N/HmOCqqBdyrFoRTvvlo/YwHL+C1vgC
lGrlwTz7HPl+87vfSCCwgvXQgd3du9gYJQEHdnceT1CBxYHdS/OceVBFad4Ab/0FowsAFfId
2K1/n1EiATPdA7uE5l0VOP3wPZ0k5JEvRvhXO8HzE8tKbyAxClPpBeFIu67XToaTrPcioqrZ
MjralNoCY4xs7Sa5MhVNWJmRUyLf99YYK9cusj/L8ssn7cezYFryWKjXHDJ0CvZitjWklfiX
D9rDaJywdSffkpms+8UCLdf2FRYs10I/n5PhlETEuZTmd6PewftRebt8LKB53yAQiKoXD+xe
aldeN3Xs7zuwe6mdhmsHSO0O7Nb9DdeJDI5sD+ze368lPwRgkcDA7iWePdUOJiEGdgF3yHI9
LCCniYQ8M5HQnC0SHCG9AgZU11Q01W6yKlPR5JTFOUmtysQMjtTHohW8zq5nQeeiKUnJGVCJ
UF5iv1hOZUn6rly34clpIfEomKgbN+OmVqsQ6GrLq2Zsruef5qKhVIXFGV1uVnLGp45X9Eg6
BfvVk/YwnJzEg+j+2pRitaNKMvKXnEr5m6gEVgGdCwZ2d4HWH0i4QBvY3QVarmje4MBupnfl
wVjvAO8meBU2ED6wuzOLncAdHtgVBO/SDMPP3dM+Qp5o+tdUWIuv8X8wg69UXdLMn7VeTVF/
TEbzIniSW5faSgMdChYRvJfv1dWxOxlNl1Aazq+SM+jPu2hSN8tVc+TPJ+3Hs2g4aXVu4i+q
9Woww9MlhraX0XxMRhNzx6X6h5tKLU3AzoZFujL5MhH5ORmOvwOZrVTyy7xJgeXT3wzvX2d4
27UCuYIlsYHdnblrCr5OA7s7c2fwCN+B3UztxF9LVBlqgLdTOwXzFQO79e8TSiwgdxjYJUXZ
mwP3NJGQJ8r+4Vtd2HqvxNVgA9i6Jnd3VVv6mIwmxP9EhZ3Zce7wAbVEMPAymM/JYKIfKsRQ
apUQtQalUddwodvc3Wkh8SiaSMORxyPB61BFmUW5uzt/j7logqNF010xirIBKF60SlHmLnc3
FU4O61DO0pjEXyD0xZmrN72Z3e+hGIi6VAzs7tydGKhRMbC7c3di6AjSgd1O8MzQ1NgA791h
SsXQJ/DA7s3dhfU4OL89sEuKszcE7/SSkCcC/5E4Jr+sN6niJBTLD8WiJQTvKtv1MRlNTn5M
Ua0lOyvC7QrKiuGKpleZyM/JaKKrqWbrxsJaQVk6X7RmuOKmDeC0kngUjZM1qi0bk6qhhXNe
cpUIWe1fPWkPo3Gu1lumosHyWu8ow7MVXXeFbtLEU+H4LYet+jnE0dwAd6vO3Vp/d4bHX6EZ
CDYaLWnOXjbysV2bDx3oDeRePsJ+5qF6LQd2e7W4oRm7A7v3RmGWqnSwHWCAd+9wa6Cy4cDu
3WEqqWfUOnCAlyQVb5jAaXUhjwwIahQle67snNPQVqC6pCiZtd0UjOfCSRJqu2Ewl50JoB2B
K5ohsl26qnxORlNTaUzZLFeyBvbvxKIlpPMqEffzUfvxLJqWWmfmnLt1JdC0NBYtycPdKLZM
ReP00T+LXIxVSiVQy47WuMQIXYXzORkOpxLWf7mXVjSDn14/W9+jHqvo3Tcp83UCneJf0L0s
oOKl2YHdzfO6gl4fA7ud50kDUxUHdjfL6+hQxcBu/ft6S/5dx/6+gV3C8W4O3tPvQh6ZEESO
sFBVyyXDTZirEot36Z65cJJkpdK5ammKyv9PVsD+kFi8qedNRRN6or0oF+mkBGYmdI3Ab760
Vvn5qP14Fs2rczfycCEwqAwKHq3JxGW9SWFPReNsTWPU2h+zMO8AM/KxagnH++Wj9jAcTmTZ
slQjq2D7aax5U7w1FG+7KJ8w2tF+YHezOxJQCGlgd7O7VsAv2MBu7gvwmz6qKXeC9+6wpaiV
gfzzhd27w/nVGwRu8QAvYXg3x+5p4SCPDCksCnrhm9VIMqiiEYuW9Aa2m3HLuXBSLTWUY2vt
Bpui1jWyfDet+FPB1KRmompiTlFASRBftIbg3cwXnQ4Oj6Jxgke5FcvVP3hm2OUyFn11Em8q
GqdqXSSbsFX/D9gkHKuWELwrzcTPyXA4FCBFS7HOmcGmWp4U03kzvN9Ilo9BHjCw22kAgURq
YPfSAEtCaC3vwG4mepoU1XM9wbt32AxVrDiwm8u14VSN9oAO8BeXa/X0cNBHwvr+txk7obBe
nXiBQzd1Uln/n4meXqfyJsNJ2jXn7r938x8LYxN5CZvIVq+Z3lw09SVH081vqhy+cCDTWzFu
VPLltPLPR+3Hs2haEu01mGtVzWAZoS0ppd8yvblogrMp5dy0EIlfLVAB5hXE9S6VNxcOJ6q5
tNpCj8ZAAeZY9GZ6//IUyHZlPoK9tQ7s3rO/JPPXClbmyytG+J4q86FF2gO7dX9joqN0dHx2
gPf+gs05OWr1cGC3/n2iyQ9d7A0Z2CXc7nr8Q0//Bn0iqh85H2KWEMrrGRwiXZMoylqvc3hz
0eTkfNGPKKnc/R+ot8YSP3S7rDl/TkYTwgTZXu5pXFBDq7LGviGXqy7Jn0/aj2fRsH+Gi1kt
2lppDa0E2orxjzvplrloIi+fLcgd95JRy99l0i3XSby5cOJ600kzca2tVLSFdS6V/6Z2v4U4
nzVQMuAF3VymBSu0u4uzMR4FdzLxdr1l8eszOrs1wLtZXUOHZgd2L6vjGEzA/r6BXcAc7oZ6
9XRr0Cca+v7w+d+WOcYsjcChm1j01axuKppgddwzFaLauICC4r5oSe/dddP7XDQl1U61iDrf
JrReFouWdKvdsLrTreFRNJyq3w2t1/AXI7QgtKRs7qzuWrZlLprgZ9I4eiNzlVdv3z5WR+V6
qHcunJy01J419+K3CFC8KU/a2b1Z3fcK8uX6wEqj7rfSaODw1QHdna4zQ3nTgd1O7Ax1Cj2w
u2kd2v4VyN2JOkE7Kgf2qxN1p1GDPjPRqGy1tyJ+Q8+goFhdYgbglO4mfTIVjbMzI2uktVR2
bodSuhUVZbs0Wv2cjMa/WNYjiWpE+mrmwxJ1S7rt7hJ1p1HDo2gi5xbC112LkBQ4UbfC643s
KrP1MRlNkDNtwlWaWlPwUVukxHebqJsKJ3JupbP6Tah3huW834m6FZTum5T4sqD2qAd2L7PT
aA6ClfgCuztphwqrH9DNzM4pRwUr2Sd4N7fr4D34gO5O2FVUs2Vgvzphd7o06DMHDaFsOVtr
xYqg7E5W9KRpvUmjTEUTuTfyM9eUnReB5t2LEnZ2l7CbiqZEqU8Lx8FbFSxclkWVvsvR359P
2o9n0YSgXqdqqh4S6r4ZWb4lCbur1tSPyWiC3VEl4ey/FAnYk7YqYcfX2jtz4eQkvfVGjaIj
I8MJu7+kIMqXqPBldHR/hZ7Rn1iHT0D/9QO6l3FytNWiAh62QjTsYZFYwM/qwO69T1hLGR1L
OMG791eJYIWWwO7d4aDhDZV5G+AlOcWbwY7TQUIfyfpboty5iB9l2hWeRlrxg2fVG9o5F04S
bkSWSwn/V1iHb4kzb7vJ9ExFU6M9I8ZeexA2sOpd14xC3FkE6ukg8SialhpzmK40lgb20MSa
FaxTr2ZuPiaDoWTRYcpayC9rWeEJ3jUSLTcjRFPhcGIl8ZuNNCMFDdtj0V+Rdf69ZPhAm50X
dC8JsNBXh6c7A7ub5jW0v/wF3U7yGKzcDOze3RUnRWDn0wu6meCx38PBnPYJXkLwrr7sfuqe
BhL6SNW/xly2f91zVCcLnAafSyj8QaLlZp5yLhynRLmHNW+WnkFVk1i0guDdTe5ORVP9alW1
+4lbnOCBBhLLJnev1YD0NJB4FE1LVlioFtVmFRRgaouqxneTu1PRhGSyhSsTvVQSGRbhW2FH
J3RVXvicDIeTx2D+JbDmYYEJeZ406H4zvN9Aha+gNdmB3Xv811QJPI0Gdju5E7CqOLCbewJq
6hUdkhng3TtssEH0gd27w9lZW0bTtAO8guKVm8rxadegj8wn/PLDnKlklYJKW74WLcnh3Ry8
c+EkdXanJLk2BrVvQ9BlBcO77Nn8nAzGH+yw03Ly3Zp2wd7XWLQkhXeVkPz5pP14Fk1LNexa
QgPk5d6CqvB9uTbLVDTO1Rq12iOfVqWDhJXWaGDfWWnMhROuGN3JKpWSTcDaXeJ3W+AqgvdN
InwNHT0f2L0soCV/JHEZmbLCm/yhCB9qSTawm3leFOjQUugA797hw1sT2+HAbuZ54biJKvEM
8FfXak/LBn1kQBFlV2oc83zE4PzHslrtZXXzYzacVHMVFdLq5zBcq13RhpbtUjv6czKa6OMQ
p6yq0rOB9cBYtCSVd0P0TsuGR9G0pEzO83yHujZwLq5Njo0+IXpT0ZCfe+Rs2MycGxW0Q3CF
LVEpd0njqWg4hR+0+WsTsjNgDsUXTX3U3kTvezX4cgPvjAO7u00rC+hjMLB7j/7Q1QM7aF/Q
rbsbY7oqcI3xAO/9/fyLLqhE4IHd+vfJS/kWHOw9sEuI3U0C77Rq0IdWDd2/550bRaUJtWpY
Ikd8O9g7FU2I6fVei9XWraHP94bB3qlowkM5hP2sdRLURiMWreB1d4O9p1PDo2jYbze9OOk2
8Y8x7NSwRoEv33R7TkVzOOMUKqVRNVAqesdc71Q04SRjuXJYtvj1Dp7rfVdoF/C6bxLgq4TO
zR7Y3RW8VkEhyIHdXaNlAUugA7ud4HX4ABzg3QSvg5OmB3QvvXNOruBg7wu6gEDczfXW052h
PnNnkMK9FHN6HLINaBP/kqTdjRDfXDQxottfQ8qtZHR3lskrXyft5qIJnSmtxhqeJgVVp1qT
GHrloe6ftB/PouFULR6xIj1mYOC53hUNa+WyYe1jMprgaaVoL90PvlIrxlU3sLu5cEJemSkr
hcSywI2rc3e8N7v7XiE+FtRe/sDuztoVcLT3gO7O2VlHe5gO7HZSZ2hB9gTvz9qhvnIHdnfW
jgtjWcWB/eKsXT29Geoz34zKmVrrzXkQ+oPXRV139VpGYy6aSMCJUbAHydVg34yvztrNRVPC
Sk9r65lV0AqKr1nSdXc9wlNPZ4ZHwThF6xyGJqSNDGxW4TVy0XcCy3PRvASW2ZwJmd8k1LYK
LN/yuqlwImsnOYx8qTCBA3ezptFvXvdbqPERo2OpB3Z31q4rqhZ4YHdn7QQ1qRzYzQRPEze0
X2yA9/6CPTFKQF/Q3Vm7Cp5RB/Srs3anRUN9Zp8hlP3/ahxWqCDCMjW+G3I3FU3wtDjKqwdE
paCiYmvI3V3WbiqaEvLrWqWIxeUKK/uVNW37d/YZ9XRoeBTNyz6j+DXWiAqBY6aL7DPKjQDP
XDSRf4sBEYpmSMqwJ9qSCZEb94y5aHLyVz8q5l2Locw7Fv0Zyd0+6vZf//jvf/z/f/z3f/7H
//o///f//cfW0wnsZN3MiEAytOBrvIB2f4ccodSQKYNzRoHdnVPlDlbDBnY76WawU3Ng9+5v
S72B78HAbv39aknRNYWxwAO7d3+5pgybdg7wkqzq1ZHrdOg00qjPjDS6H7RZWnYWgR65vmiJ
G3G5kkT5mIyGU8htFC5NMhv4AoZi6YJo2o1K3Fw0LZXmWx4WfOFAg12KYtEKcqe/fNJ+PIsm
J6rCtSmpaAWJdyxaEQ3/8kl7HA1r0R5uLUUZzt/PKfj9c5L410/aw2j8hdZGOaZc1CpYLPJF
U3vz3cT798qqfqMeobxkQGCWF9i9LE9TI3DYemD3sgDzcx01sTuwe/e3p9rA2v7A7mV55J8d
cJR5YPfub+mpow2vB3YFx7uszvrJe9pp1Gd2Gp2oM1NX6hUVqfRFKzje5azsx2Q0nFQ7q4Qk
YUgtghxvhdCBc7xrwZq5aCxpq1rVmX3mzlhy1ZbI79xzvNNN41E0QdcKN2d3NfeGmkAt4nh6
w/Emo2GKXtUsJTe0BhmLVqSK2y+ftIfRRBo/xAyEmjoDRyer5jITb4733YqE5lunoOz7wO4m
dzWj0y4HdncKzzI+7RLYrfurkqyD5H1gt/5+FhpxYAZmYPfur3AqsA/gAC+hd9c6wPW0rajP
zASKNefGpWqL/n1UanZJCo+u6rMfk9GI/2FCNediygWdR1oTTcs3iZWpaFpSCw2hw4kDdHVs
kxXNP9TOb7o0TtuKR9GEnwZnJiGW2jJcbl7iwpHpZrhqMpzeJJM6tesN16lZkfsuZNdOdnPR
5NRrz6H3xVSN0Pxq/1MWz39LfvcdOTwLVxhQXnxgd7dHopowB3R3Bk9Qz8cXdC/F06QohR/Y
vfk78YMKnLwa2M1VWkuZUNu4AV7RHtlu8iqncUV95ibg/51Vw0xAGVQI8jUryprKN5Omk8EY
RSdhe1Ej8OOwRhQlN7oZfZmKxlKzksU6+T9eDntQAm+Fwc6NdN/PB+3Hs2iCq1nplaWHqR8o
phDeHUvCuWmPnAynNSpd4p+5Kai9EKuWULyrm97nZDg5tdqp1C7CWkABnjz5rL0p3jdKEUoJ
LgQ2aB3YvbSuJEOHIgZ279GvCXQ7eyG37m3piTtI2Qd262/HOeGORQd269+nPWUGE3cDu4LU
XfIgP2tPr4r6zHgjBpkrW6RSFOy2jUUrWF27ynR9TEZTEhGphHFurxmVoPdFK1hduWF1U9E4
3SyVfNMl0miEnbS8ykfkWsm8nlYVj6KhVFvNhfx+IzmjU7O0ZqSZ6k2KeDIcE+pRNfed6Rks
zMaqJST1KpzPyXByCg9tiaGkbgpOz8eiN6v711ndt/TdRcUGLH0O7O7SbAa92A7o7sKsgF0/
B3Tr3jIlXAvswO4md1LBi8XA7iV3lkoDv+gDuyRjd+3oUE9/ivrMbaOVEFLrrYizCJjcLVGr
kRtyNxlN+P+G2F2PyhVcW1qTsrsZM52KhpNfWfy/t8TkLDe0g1BWsKF8OQL880n78SyaoGlh
d0eaK/tFApZlXqJXcynw8jEdjhXzN4aaP21GYPmD1lDv6x7Cz8lwcghqWVOu5BGBNnGx6E3u
/mVyt7nbPqbiQFPDgd2dsgsrajRlF9jdKTvr4MznwO5O2+UCMqeB3c3sakUtqA/s9rSdgC1D
A7uE2d0IiJwOFfWZb0ATIdUW04xowS8WLUnb3RRjp6KJDJxUap2rWUd1rDak7aai4WQixYkD
x2wm6sm6JC+UL6nDzwftx7NgnKKZOW0IPaRSGBd3WVG85MvmwY/pcMzfl64ekuZewUdtR9Zu
KhznaKatRLOHx4QPAL+zdguI3Tdl7cBZzxdyd8ZOOqihN7C7c3ZqaK/9gd3N7RpqrPeC7mZ2
hB5mL+jujF1G9RsHdgmvu7ZzsNOcwp45BrxahUK3rwl3MMPsi5bwumsJwulojLp0cT4Ux+6X
tgr9YYzi+rCdi4aTKPVQhquaGbbakCVzBzflWDu9KR5FExTN7w/dir+rSrY3Y6fXdr+z4Vgo
glIh35xqcAJyicvdXcZuLhznaLkUy7VJ0QZmh2PRX5HYMUzsHvWNgy3jC75Fy6Y79gvwCeg1
PbB7CWeI6qGq3Ad2N+FkRk05Duze/Q17NwGvEwd26+9XLfmHHHxPD+ze/ZWcDq93aHr3AK+g
nTd6xHZaZ9hD64yu4idoUa6S0ZzVkgTcy1/3igtMRSMpSxUVyqy1gA+QL1rR03g3vTsXTUtV
OPeWc++EdgG2SYvYB+IsdlpnPIomdFaY2Pxp672Dh8sicZZ8uTcf09FImJpQbiXS8ShNWzFg
WORyFPlzMhp/oaux32qrP2i9oRccek92rKJ33yTAV9GS2MDuZXn+v9nB+cmB3c3yuqIfsgO7
d397qhmVsDiwe1mepo6mZQd27/5yTwZa+A7sAh5xJ8Bnp4OGPXPQ6MU/79UPXz9+wQd2jT+a
H5E3+Z6paDi1nqO8arlIBYXEYtGSZsAbjjcVTUtFhn5OqVxAw4K04ktyz/FOB41H0bw4Xmh5
SeRJd4ssXwu0zEYjOYxNclPVjI67yoq8ItO1PstcMK+LXg9tlsyMml/PXvTeFO930N/LYLvd
wP7b//4fAAAA///sXV125Dav3BEPCAIksQE/2PvfzwVaVB5ujpQSQ9P+Jp1Mfh6KM0ZTLRbx
U7W3ZGwd5XYHdje3a+A96IBu3d1Q1AN77Q7o1s+uxWAEeK8Y2M2tnpw0o8IsA7yE2V33aLXT
oqE9M5xgZ+09PDT83Q761sWiBdHIpcXy52Q0kio5X7Ts8SiBFwNftGTMQ6+tYueisUS9+/Zw
YW7Ov6FofNGaMY8bZndaNDyKJpRZPAzO3blDZXA+b5H23jVR/ZwM56UU3ar/Q+rBgK+CRcnI
G+O6uWjYn5omfnFk3yO0oM8pv7ndKm73Q9p7DF4YD+hegucHu4Eq3y/oXgoQcnpoR+CB3Uvw
NCn6kh3Yvak7SwWd5hnY7RTPrzRgBX6Al/QF3hy8p0NDe+Y3kXtvOWcqVgvokLZMfO/m3J2M
xnqxQlKaNXTQuqzxe+v5et5jLpruVyuLX9mf7wJeF/uqkYJr8b12OjQ8iibIWs/+kOVewpAP
VatbJL53U6GdDMeksT9mYWGnpWNnUfj8fDfHmwrHOV7r5F+dZlF3Rv0z5jyV3hzvZ8X3KupL
NbB7md2Dn49/4OcLSb2Cmv8c2K37+xLVQ8ULD+zWz6/4eYu6Bw/sXu7p7+gKWqMM7ApmdyPA
105zhvZMMb+rOu1UFlICE0ShwbokeXetdTsXjVNo4d5DfK9lAwcSY9GCaJrdTHxMRVNSF+NO
PVe/moJT7Uu0ETlfCtb99aB9PAsmBj66GWfJVriD2a5V+nuXPPVzOpzmW0I5N+JGlVFit2JU
6qbK/DUZTk7C5lsjHJ2rqGxskqnujDex+xX6e4VR39sDu7vtjgrYNjawu0uzaNfiAd26u6Gq
h2YWB3Yvu5PEYF7sgO7mdl3ApPbALsnaXevvtdOWoT2UyveDlvzAzVQKOIiwSn+v33C7qWgi
jVCdAEsLzQkwk8JLSpn55SB9deBORRMGILVkslwz7GG4xgDEyd3N3PhpyvAomqBp3Epv1kia
Hxa/htxNhuNk3uNQ6ircGKNDseq7yd1UOM7TSEqvKsUJONwQKe/K7L8nd9v191pHR2YP7O6s
XdQo0KxdYHdn7VoDvaUGdnfWjgxlxQd2e9YOHdke2L3MLqRhwJ9vYBewh3JpEOvn7WnN0B7a
ZoiY8+JqRAQOzC7S3xO79pifi4ZT1jB7D2nl2kF9WF4zMHubtZuKpqReu/Nfqp0bPsa4xAzt
ZSZ+/6R9PIsm0nZEzQlEpIca2LK/SIDvltlNhuNkuzQ2v0M40QJ59w5mNxVOpO38plXDK7oL
enC903ZLmN0Ppe0aWAk4oNuTdqj87sDuTtopOo8ysLvpXUfp+8Dupne9ot1fB3Y3vcsNdG0b
2CWJu5t0ymnO0B4aZ5Aft7VlP3sr6A7ri1bMIGi/oXdT0XAiJVVuSlIYVehMKyQc7xN3U9FE
4q70l5lqzg3sjo1FS+jdTYr4tGZ4FE0QNafdXLmWzhWs/++gd5PhNKeqlVrc3DwyuHtwjRPx
Db2bCieHaFhulZVyFjAN+acm7r5Fhi+DZZ68pMSzbNRjvxBfBrN2A7uXdvrrtYL2UgO7m3b6
4QfP8QZ27/5aIkL398DupXVOdQXs9RzYvfsrYQYBNgMc2BW0806G73SOaM+cI17uqObXnsOH
HhNnWMI6L1Okn5PBSGLLlaxka5RhFT5eUi6+G/KYiqanGKs06xLDouCNoK8yBLsZJzp9Ix5F
EzOsYj2uBV062Du3SqGFb+43k9FobqalhB+voYQirXjJM9eb+81UNOXVZlFzpp47Gk2ZbLP4
7Zzzv6TC1xqutRzYvRSvJUV/voHdTfG6ovn3A7ub4ilo53BAdxO8AmZSDuh2esfwRXGAF7CI
Ow2+flpI9Cey/pxMoujVe6bmv1ANviW2bTc6y3PRSMq5lCa5FmapmOBELFrB8PRag28ump6k
WOMuEVIFb2O+6Ls1+PppIPEomiBrVEicF+WisPXKIg2+ayOZ2WikvzzOeogvVpSvrtCrZ7Jr
Eb65aJysCSn7JSVaHEHV6Fj0ZnhrGN5+ET4GJykHdnfRWAyd5D2wu6ld1BRgFT5Z8RJ7KMPH
YNFzYLd+fs1S6yA1HtjNPZ+hS4Sqbw3wEnp3LcTXT6uG/kxAn6txLq36/azCCTxe4Xeml5oz
n5PR+KMaU/tFuDvjB40nZEkpL3e+LuXNRWPR49icEfWmCpq32ZIWx1sdvn46NTwK5qXDp5mb
SUzyCux2tkSH73JO6nMyHOedVp17q1QTA1sc86Ry3d/o3c1FYiqakNSrzdlq03gNoO0Wc9ei
N737PTp8RXEhvsDuZXk9vmTg5MKB3csCWop3GazFx7vFljWJgnojA7uX5XEyNZDlHdjtLA+t
Ag7sktbAm6P3tGroz4wnorrYpLy4Edp9tmK8O+ul49PnZDDiP1jlLmzN/0tYlkjWyAre1Wjn
oul+d1HJtZVeuoEWsH3NaEHWa2Ggflo1PIom2JpauNpyGMyCkiCLhPjyPz9qj8Mxk1pqb87t
CTXSiFUrwrkR4psLJ4bhW6lC3V9WAt4nZofh3yTvZ4X4nMbDQnyB3d18l9GRyoHdfPBHtRXV
4H1ht+7vS1xPwVvagd36+RWNrjBQq+XA7q0d58SojcbAriB2N0J8/XRq6M/MAJw8qIpQbmHY
gM58rJiS0Msh2M/JaDixH1C9kRg1uNDMK0qzdxO9c8HEJFMYo/VuVAW8RJQlGom3Qnz99Gl4
FE0Mb0SuS3MI8jFYad6g1TIbTs9dWbpWyx01j/ZVK9rv7kY+5sKJ4dzM1Sldt17xUvN7oncB
sfspIb4Knq8Du7s82+DE3YHdXZ71V/IDJb4VYnLP+J3fPGF+F9i9/E6SodpwA7ub31UDvx8D
uyRxdz1p2U+bhv5EOj/E+FphcY5H2tEa0xotPrvJpkwFwylzCJxYFlYD09K+aEU0nW8Sd1PR
hFCC/67VCVFrFbyLlUWZrhstvn56NDyKJphaDodlJiEiOHH3/fxuMpxOWokLZ4rxJHSkd8Uw
/D2/mwonFFv8PeA7w/HQgeeWL3rzu3/N77Zr8flhDmvxBXZ34o7RxNjA7k7ctUZg1/2B3Z64
QzWWB3Z74g512H5Bd9O6wqD/yMAu4A7lsq7kp+3p0dCf+mf0mjn82a2Dp9Mi/wy1m8N2KppI
wfkFJGsrKmRw3m7F3tzm7aaiKan3HjItLEUr2KXmi5aU/G6U+Ppp0fAomsjbOa/rqlIJVU/f
oNQyG03Pktm4Z4vBZqz2v4PWTYUTDK1y8dunckO1Mt5pu/9tIT7Bjq8DujtpZx0sGg/s7qSd
isFJu8BuT9qBsgQHdHfKTqzB9hmB3c3tOoNplIFdkrK74XanR0N/6J9BnYm6H7elFow/LJPh
u/bPmIsmWobEnwWN9ifUiXTWu/NJzm4qGn+nFm091NGyGCiNVta43uZ61bP/15P28SyaoGnO
hpTCxZcq2E6zg9xNhuM7Uyu1XmqIifwWkeW5aJym5SJOU602Rj0fY9GfyO34O1T40D7m3ZVF
kJ8seEEu4ME/pgyIvXsP6O4MZxjeoBnOwG4vXcMewQd26+6aJGWwE21g9/JMTkLgu2Ng9+6v
P/NWwdHsE7zgZcL1pjnx9LToT3wGNDWlkFqR2iqDJUVdMu+Z9UawbS6aEl0qkv1WGTMt4NhJ
WWLdmvvloMbXZDQ9mWSPwpxuGYPq7H2JqM/NYMNfT9rHs2hC9zvMRtToNayxUSyc6XIi/3My
mpyKVjLKIUpNjN4gV9gisNBVC8vXZDQl5fBZNw69Q1S2sUyOa/12IvxfkgYU2FPuwO5leRpz
dyDLO7B7WUALRU2QBBzY3SzPUE+Zgd1eKX5QKF5RJ36yu8WSNLC/8wSv4Hh0c/Kexhb9idmA
Jg01XhGuxRiU0/NFSyrZcqPpMRVNSdpb49JyKdnAk9cXrRktvkqofU1G01OuIdhWpWqrYO42
Fi3Jdt7cJk5bi0fROF2TwmqlS4hzYz0TPClA9zepwxuONxWNv3NytBk0adEJgpZ+V9xFudCN
OOBUNCURkW9NayUzujex6M3x1nC8/eKATWHZjsDuJncVtaYY2N0pvBg7Q1N4gd26v5lKMkXH
YwZ46yfYXoOv4BN4YDe3oVpC+3le0BWlbL1pHjv9I/oTVf+amFvvUpSKgY0XvmbJ9MmNtcdc
MJJCWbhFhiPE7TA2FIuWVLJvpDymorGkzropU/YDF4vFl6zJd910TJzmEY9iiTY4f8hIoiVW
O5rvmmuDe6IZMxUNJeutiFQOYcAK9qIv0oyRO2o3FQ6nbESs4cOoVlHa/U7fLaN2PyQMKAQK
BA3s7lbFXlD9mAO7O30nBez0HNjNDE+SKOouN8B7E3iSLKP2bQd2M8MrqYK6EQO7IoEn1/LP
djpI2BNdf/WDJxerzJkPEwQogbfitMp6aUb3ORlNSY2LFj+ynPI3hRv8Voyi3GkDzkXTU485
FAu7M7aCve76d087/PWkfTyL5jXEaqqtV98ifNphScpLr2neXDSU4mJUekwYl1rBtvlY9a0V
9K/JcELlj6twLr0KKiz2VgZcwPJ+QBkQNVYY2L3Mzv9MAi9NA7v53Hc2CQ5svqB7d7ckP/pg
XaDAbv30Sk6tgs2VA7uXdYZRB0iLB3ZF5k6uy7J2GkfYMzn/1gqXsMAIjwL0fb7EBkP7tWfb
bDREVXN3TmL+u6MDxks8hlu/zqjMReNfOyshpWfirwdYOGZJfohuFCjtNI54FE1OFK4xuXeP
CuyK9DUrcndFry3b5oKhmLmszrmJ2Q++jk7ULBkQunag+5reG2nNXvbc3Qr42p11oHuzul8i
C4iqxxzY3YXZDJO7A7u7MCsZJHcv6N7dlfgjQXJ3YHeTOz+dwQnjA7uX3PntW8Cq9sAuSdnd
kLvTMsKeyfi3aAzPRUKrDTtyfc2SAWO7brmbCyYnYxHW5hFVtGM4Fq3I2NFVNvVrMpriW9PI
nKlyFJvh/OOajN0Ntzv9Ih7uDbFkE6s5FA6xaGLRimgupXA+J6OhcLEsrXJzUk9aUPGYtoKr
3g0Yz26O+G9KxKUbKa75/O65+/fkbr8mIDov+4LuTtj1jioCHtjtCTsCR8IGdjdnb2ihc2C3
p+waOEoxsNtTdh2Uoh7Y707ZnX4R9sz8ws9YZeq591JBbZIdKbvJaJyZtmbW/ehzDvFrUnZT
0UgoXeamVZpEIhLsHZzrb39C6063iEfROEPLUYM1J0KKis0uo3U3Jf+paCL7Ruy0WzV2HrR8
3pGzm9wcf8aUaiVtrYDemLHoTev+Pa37KU1AUB7ogO7O2AkqhvKC7s7XqYI3nxd0d76uVHBM
ZmB3M7ssYB/OwG79+dScEoE/38CuYHZ2c96eThH2zPeiNuvNst/TG6rswktk2rLeqFPMRZP9
Cpe5MGvNWUHlkLyk7yn3y4rf12Q00ZhJlDUGKVrrqKpL/faE3ekT8XBvKEtl7i3uEGCGKy9h
3Vwux48+J6NxjpaZxYjCdQ58z9OqZOpNanhyb0qtfiPyeKQWsJnTF/2RxK58hyBgBZMAK+7/
y8Y7Nnf/aTKYkhzYvXSzvObiYfG9vOJYeUY4S0bPvAO7dX9DaqWAsjEDuzdZ1/zejYo8H9jN
yWJNpYDGhSd4RZG4Xs0OOBU4bSzsibeAph6WwGK5BSPAItIlBqdZ+SadOBWNJKdoWfwT75ka
2H8bi1aQzrtm+6loLKn/rrV6OMyv/gBsfHdFAu5OfM9OF4tH0XCiqiH+83rYUE2tRAsS1zf5
t8/JaCKVVmKyo4ZNIXgUzebf/ja9ezNBNBWNH5HOOLN2ziEChAoazV2kfzvp/E+J7yn4yh/Y
vSwvNE3ARqyB3c3y7AHLs+0sz3lHBfU4BnYvy6uJwDP6gG7meOwXG1RBe4BXcLxLSWI/eU87
C3viMaCplqq1dephUodyvCUXYKWbdM9UNDGOxI00fgkYTKxZkle8OXingrFEEkS1CBOh7R22
Rq3uTnvPTjOLR9GEVHIhf41QoyBGe/WVb0Z3p6KJmeK4o7RexAo4TrRoEFkuvzZfk9GUxFZi
PirKxgQ20MaiN8VbQ/G2a+9VA7ndwO4uGFtHa1wHdje3awqeLgO7dX9DbKWiKdATvPUTbC0V
BrVtBnbzDjunVDDJfYJXFI5v9PfsNGmwJ9L5NbGoaKbmZ3oG3U590Yqsl1yWwT8no4lHtVIx
kWZMoHSOL1oy6XEp4Ps1GY35ta+QH7lFtRn4tMWiFQQv3xC806ThUTShpuebwupfhcLgjJkv
WiOufJWR/JyOhmpp7F8bK5xBGbNYtCS/ekPwpqLhFOqItZQu/iol1IJxzpz1TfB+kQJfAb+I
A7uX57XEqAb0wO5lAc48wPm7A7qZ5an/maAMzwnem8OzJATu78BuZnkS3nYgyXthl9Rpr+pN
fvKeJg32RDq/vs6qrlKLH72gP3Ndclbl1wzk1ck7FU3IlAiZVj+wKiz0s0ZNsOcbjjcVjT/W
lc3ptwj1Bk4WxKJvTXv99aR9PIsmOJ4YNf+gRAvMipbILFP0u90/aQ+joWR+M4qUV25SCCxt
+qoVOcnM1y5pc+E4X3v555DUlgV0DfdFUy/dN8n7WQE+RS0KB3YvseNUCzjiNrCby3epF1BD
ZmD37q8kUrCDbGC3fn7ldUZjB/MLurt0zIzSzgO7InV3N817+jPYM9n81tmEc47LO2g3HItW
0Dq7OWwno8kSxUw/nWJoFDYBWJGIbHajnDEVjaTcfUuqEwe2AiciV7znbpJdfz1pH8+iCTG9
SKkW9X86OGm9SIHv5aN9/6Q9jIZSmMSS9bBoqbVjXxxaYrPMdNfpObk5qhqGM8bFn2R0c+aE
sd607rco8MFqHoHdXp6taOvdgd1dnoU/v4Hdze7UUPnsA7uX3UkqGaQbA7uX32koE4NZrgP7
vfxOaFgzxP884ncsLboDWiYmWK1lyXjFdWl2OhqyGqPJzoi4gS6+zu9W9N7dqLVMRuOXqjDv
zRapFOzIlUXqJtcTvWcsH89iCdmVzpVVi1UC6dD3s7vJaILdZa5d/GZUGTfNaEu0ry/7b7+m
N0dzbUqWi98o0GrO5BzPm939rAQf7Dc2sLuTdqjb0QHdnbJrHSxtDexu0t4VJXUHdjepI/Dj
O6C7U3algB2fA/vdlC6ftOGpZ0bT8IY1ZgMz9KtSdnSpqzwdTdYewmjW/HQyOGW3Ym9uUnaT
0Uhi53RSfF+ccIO8IRZ9N6nLJ2946plRWm0UHr4VdRNaRVFvSN1UNEHPVKtaK8LZQA2d70/Z
TW+O70oLb5amig8Az2mLvUndrxDgqwZqZgzsXm4X3T5go90LujthpxUsFw/s9oQdrsG3ZBLg
WTG2VzRdd2B3c7tsqLjygV3RZXfpC+snLp/84ZllRjXKtSq3Zgw6GcSiJem6S42K6WhIpGq1
kHhBs9G8ZLj0Pl03FU00GdRaqBOZofTh+8WVz2g+nkUTanpW2Z+14g8aboj27dxuKhrndi3s
P7rVIt3AWjktUSW/T9hNbo5mcbbqlwnRBr53Y9GfyO2+RYMPvZvlufGUP0eFD9WwekH38k3n
GQSqwg/sbsbJCqqfDOzW3TXxzwR7tRzQvYzOUi9gHWlgN+eKo+qLVSAHdgnjvJzdFSonq3mi
4//qPFWWVkLmDWScsWhJNvHSZGEyGklsmq1ZLl0a+PhIKmvEWW5SPFPRWFL/2jkRaFWbgV1Z
sWgBqbnR3zuj+XgWTejvFfOrV69VssDiLEumVC4p2udkNFEeJSnVL2m1VFgmeYk24o3+3mQ0
JZUoeKuWbqWB9DkW/YmE87+kv1cFTNkN7F6G11Il1BT+wO5meB3VZ3tB9/I79ZMA1Vg+sLsZ
HtxCObDbGV6u4NfjBK/geHKpsSwkJ494IumvyX+yxuHuUVmxgzfWrKB4fEPxpoKRlDM1Ja7R
di+g36QvWkHxLl3BviajsZRN1aiLddge0NYUjG/0985oPp5FE7nbEPJ29vjKku7V37tJX09F
k5P0RsVJXnRpoiINSVY0AQpdzUZ9TUbjbI2rOL/LVJ3qwRLLUxe9N8X7Bfp7MZeE6u8Fdne1
WMHX3QHdzewaLqzcNusqh5yeZpSZDPDWz69Z6qg818Bu3t8WugzoDh/gFd2Ad/k7PQnEE+X8
mC12CiFmfjtD/TNi0Qpy1y91WSajkRCytEYvtqpg4SsWLSF3N92AU9FYMmtW/ZwuoYoG1lhp
Tcn4RnzvDOfjWTiho0fcujQRLbjlxBKt6GthluloMlFoXmvcLFHj9SWzRDE3/E+P2sNoOJXs
RDX7tggV8I4Xi97sbhG7+yHxvdJAFjWwe0le9+8LeCYN7F4a0JIUBUu0B3Yz0VO/taHFhQHe
S/RKItSHbGC3Ez1Fpz5O8JIk3qWJhlA9ycQT/fz6cmoIxQnO1MGHtq5pplO69DaYjCZkSrpl
f1yJq4FPuC9aIsB3V6idisZSpW4WpMi5EVhEt1XuvJcCfGc0H8+iCS09lV6cR1QWcJpwFc/7
5yftYTTkJFylhN9w8f9huNNxCQm/VlmeDCcEk4uHY9WjKYyadL9VlheMfWwX4GtK4LzHgd3d
f5czWF8c2M31u9RRiZGB3bu/IaoHjssO7NbPr4i/OcGTeWD31o9rEnCg54CuyN/dTfO2kzo8
U81vvUa5TMRYwBwRL1GayGo3xdnJaKJxjEvxeGo12ANgRXH2dpp3KpoYzKUcUwVEtSrq5rtm
mvdagO+M5uNZNKG24i8Rro0KKz7x8e0SLVPRkL+wu0rTpiYk4OgcLTGOvp/mndwc1ejArZxb
NdA84z3N+z8twCdoamxgd9dnO0g+D+ju+qxQgQu0gd3N7SramvSCbmd2GUzaDexuZqcgdzig
383s+skenknlN3+ZSyvmfzHYirFMeu8mjTIZjZNUlVDF4d5RQ52UV8yJ9HqTRZmKJq5T1sKO
lFVgHdRFswh3s7z9JA/PHDOIe+1O7koztKlhA7GbCoZek3rNzKlqaRk08d0h0zK5N3p0ELIq
l4xq6Oi77e7fE7vNZ35JlEHH1oHdna9jAfNNA7s7X9cqSDkHdvf+9gq+XQd2L6vTFGkKjNUd
2O35OgNp0MB+N6+zkzs8tcwoHKomXIlBI4Nllhk3x+1kNMz+IVWJ5JCCblu8pn/wZTRwddpO
RSPJN8R/X2lOiBgcz5Yl0dzzOju5w0PLjGzduYPTbjWwrLxDo2UqmsjYlW5ifnswzmCPWqz6
bmI3uTl+c6AiypmF0Gbxd8ZuCbH7oYxdE1RS4MDuztiZgPqpL+jujJ0yqgt/YHdn7LTjdmiB
3Z2zU9RneWB3s7vKcM7OoQv4Q6HraYp8WjLkZwYT1Zr24ld1yxV2y1ghH/LSXrk4cGeDoVBz
8BOqqGTw5hIWGyuo3Y383lw0EuVLc/5QSUoDnUdlVZbrmtrl05LhUTQvapdVqZVOvaH1vm+n
dnPRkN9uQjfE/ArhfBU03tvglzG7OcpsTr2JMnfQHfpP9cvg/3n5vUcsBSQoC16RC4jwj4gC
vrSbwTTYgd2d5hS0cP2Cbi9cK/i2f0G37i1LS34ogZ/eAO+lmQUfiBnYvftbupNbdDR7gBe8
TPhyeNUZymllkR/5C6izDSLLWVtDVZhei1aQ4Utm/zkZTkndL+St5WySq2JZ2/DQWVK/vnJN
+ZqMpidh0VajqbpncLwpFi3gW6+e7/tH7eNZNJpKDeU5vxWSGOgB44uWiDeX6x7YuWiy/2Di
T1huvkHW0D7LJdEUurl2TUVTkr8DSuv+L6kdVAOO6uafyIX/U8qAHfWRO7B7SZ763ZHAjMaB
3UsDWiL0Uv+CbqZ5mjLYijKwu0menwMwyQvs1p/PIv8LktCBXUHx+IpF+Ll7OlrkRzYDkooq
dVJu1FHS6ouWKANe5tQ+J8MJzyMW87OqdKqgMGdZY57yelleHbxT0WjSYmy51FyLdZQUrTAG
4lfq+/5R+3gajXO7qpnJ/FYBquLHoiUU71r8eS4aZ2seDRVmzb41YNLIF63Ym8toviajYb+z
1UxCWp3jwS0gc5n1N8X7BcqAvaGSHQd2N7erhHO7wO5O4VW0AX5g97K7mhMTOm8wwFs/wRZu
LODtYmA3J/Fqkga2Up7gJfXsG4Z3OkjkRy4F/v1Q6TmbEwlG7Q9j0ZJmxZuK9lQ4koRLblHP
5gaOf8mSrFd+0eOrY3cqmJ6iUZE8mNy0gi9kX7TE3UNucning8SjaIpfc4S1dJEoA4ONKmu8
Sq7L85+T0UR53u9Exiz+/gb9MPJk1uv/R9NuCN5kND3sqHsxQq3xYsmb3i2idz8kDSgG3rMG
dne3YmdwWmZgd2fwBL3YvaB7OZ72VCqqrDjAe3N4PTEqDDiwe/eXJPUu4A4P8BKOd8Uj/OQ9
LSTyI5sC/9lyC905C9dqcMJQlihh3Bdqp8IpyamqcmlSrKEi7LFoRdfipSPG12Q01TmBComf
vKUzaBpc1/T55cuc5F+P2sfTvXEu5H/nmDcuoPBsWWN6RjcK0HPRUDLuIdnIaqxUsM3xVWta
Sq/ViubCyX7RadGwwTVsA2F57nca71/zvP3KgJXQFrwDu5fbhRohWF58Qfee/OFe2sH83YHd
ursmcWbAxryB3fr5FY6CMHguH9itP59aUgOLmQO7hNfdjAic7hH5iaR/OGqrRWmmCoMNa75m
id7zpT/B52QwUWNqajk36qxg7Xy2xvS32uy1XepcNCW1yk5OqXanDmCLVyxawupuarOnd8TD
vWGqNTq8Wom2tY2ijZz1JnU3FQ3FgdIqZb8+UIzpo7Moa0rNN6xuKpycivWeQytduBBoOJ5k
aiTtzep+hTBgIVA67gXdXZzNYOXugO4uzQoqsfSC7iV2JRHK617Q3bSOO9h0N7Bbf76QwEYd
2wZ2RdPdjRlvPr0i8hMB/zDWNaFeTJvfLdC+rrrge+687tqwbS6anKy2QiEfI5XAiWlftCKa
fpetm4rG78rdKRBzE18IZq9j0QomRFeDCH89aR9Po8nin5E/Z0RSBfUEy0uI0OU80udkNM7Q
RNVKTCT1mkEpiWW87h8ftYfhRLG4kW+OtaboyN3sAPib1/2kLiAnZ/Cwj0dgd2fr/DACOd2B
3Z2vaxWsNQzs7nxdQ/d3YHcTu1ZBf8uB3VsppsQiYKX4wC4hdtcGbfl0i8hPJPyj1Bc5hy6U
tYBJobqkZyjrpdnr52Q0nKh1MxLRUCoFs/lpRS9ubu1a73kumpI6M9dsPXcqFeuBKmvMIm4T
dqdZxMO9YRJ/0ir71jSwqMyLfEnuxGOmoqFIprL4sRI1fwZFpGhNNvU2YTcVTuTe/D1gIv4F
yobeiN4JuxXE7qd0ATM4rzCwu1N2glZjX9DdKTvN6Ojhgd3N7io64TWwe9ldSdnANraB3Zu2
09QNzHoO7Ap2d5ka8jP3dIzIT3T8/WJRuJEfvLlSA5PMsWgFu+s37G4qGg5Vh2a1sJMhWC5p
DVdtl6mhr+loWuutapFeOprmWnHLcW53M0dx+kU8jCXXmoMJkdYKvnh80RotlBtuNxVNpN9M
sv9tpRYV7D2/itvd+DzPhZNDa8BaMX+NdoOLsfRHaj6X7xAGBJnAkpadZQMe+wX4wPa1A7qX
bZZU0DLdwO7mmwXtnRzYrbvLYqkqSJhO8N58XfeHCjQeH9jNO+y0C/UuPMFLOgBvuMDpZpEf
WQxoKtn5EpmWzqAj3mvRCtLJN6RzKhxJMeiaq1llRjMjsmTgNfdL0bqv2c0hZ2rBbnrujQqY
56E1TC3Xm+z1aWfxKBy/+ecWOTguQqiPgK5RFKRytTmfk9HkJK0V7S3m3gi8E/ii752t/pqM
pqQwK4wyPnFF51RKqu+U4iqC90MafLDM/Qu6l+f5Hwl7ChzY3TzPHviN2G6/kaBuUsEL8Qne
y/Nq0ldGAOF5B3ZzX0D4ToONCyd4Cc+7rufxaW3Bj/wGxL++tWZ/wTufQCf3fNGSWY+bucq5
cEp8m1SUa6tqHZ7gXWMVfD3rMReNJa6FSVsTa0YYMYpFS2jetXkhn9YWj6Lxy0Hp0a8Z4XRw
b3zRClXB61rr52Q0+aUHRLXl5owYNFzPa0ir0LVMy1w0JdQ4tfl9vlOwVvB7M1dwetO8X6DD
VwmW4asrJAGeVY0NraW8oLvZXVNwBnVg97K7qqnDgzIDvPUTbC31An6CA7t3h1tPnMG2xRO8
hN1dZ1b49Grgh0YavWqzVjM5A8UHz1fMSIhdZ/HmwpFURZsQNTIyxpIRskZRsF+mvb5mN4dS
DYs8f0GEpzM4O+aLlsgs87VpC59uDY/CKcmvEczVahFBu35i0beWWz8no8mJWkySlKYto9bh
sWhFNO164mMuGk6i0mKGl0pXMIsXi970bhG9+yEdvixgFmVg9/K8lvyJBNtMDuxmHvAagEeF
+AK7nelpQeu1A7yX6VFiRZUgD+zmHc6poonGE7yE6d0kV07LBn5kC6Ap1FqschjvwkRvRaoo
vw6Uq9N3Kprwzg1vMY2OR1K0XEsrkpL9MvH1NRmNOQlnK8XP9S4C1lVi0Qqep9ejvXxaNjyK
xilboSKNRFk6OJ0TixZEc+26/TkZDSWr/oD5i8f/QxnUOopVC8LhuzzeVDicitRoQSbWwmCK
hyfdQd5E76eF+MAK1MDuJXf+Z6JGSAO7uYSXUEvBA7p1d00TgfJRB3TrZ1f8qGVUHvfA7i0f
WyoZFYA+sAuIw91YL582DfxEPL8mIpEuhcQKg1+mWLSC1OVrc9K5aEITxNiimlkFHx1doQkS
bXLXJ+1UNJJKax6Mb07tDBou+qI1ox/XZi182jQ83BuOdk8pksOxBZ3qXaNGfMPppoKh1KxX
0VKddGdw4ppSXzGjnMu13/JcNDl8upvfhnrphGci5/j2m9L9DhU+dPpqYHe33xHYi3JAd5dn
hVC3qQO7m9kxKokysLu5XVZwxGJgt7cGwtzuwK7gdjeupHy6M/ATyXy/U1APt3Yj7Si3i2L9
dDT/BwAA///sfV2O5DiT5IlGIP2HTl6gHjJPMcC87i6w938Y95BUGHwDqUz8mJ5V1dGFbvSD
qTssqJCMTnez/znUe52ONscm3FeIxIq5YGVBBcQSy5beri1b5tj4lkVVqPjqaGFwIMEv+mqP
ZTrDGR6uTR1tRDlIxiBCh5S/3LJljo2Lu27aXXPzMKqg11FIwhV06KY2PEWnbso8qnXpvjtC
rca2OaeMt7r7Zi++ihfsAptdsDNGE5h3bHbBzgZcsLMVLd0PZR06mXpgs2UdNVAWH9jskp1W
8KT4wH51ye6MZ6Annvm+4WH21xLF89wG9rJta8Im2qWN78ckm3AEGUJDhhQbYCrxGkeQ+5Ld
FBuJ3d4gGaHp0JNLmbRHeyLrznSGh2tD5JtrbTEGDJ6zbCuSGO9F3RSXV8XOn4kc5sou7LCl
ySjZTdGpW6vDrBbfNwp4n0WZ763p/n1N900Vu9ZB+5gDm16xA886d2h2xU4FjOM9sNnSrqMD
Hwc2V9pFcw0airZjc6WdbkyotNuxX12xOxMa6Fl6hvmrNlwg2VURWMLVJYUHl3Y384tTbCLg
zP9yZafiEgKu2K0QqnYn7abY8OYUNGyjVbh11GR5rAhouJV2Z0DDw7Xxzb/LEr/ThPCKXV1S
4roTd1NswlJv9BE50WUM9EXkV63xFbx2RJmjUze/04TqqI0KevBfN/0rHVG+xIivojYEtOL4
YNmMR3L/X0y+gl/Ugc3VnOw/YHRfumOzVSeBh+w7NHV1SYvv1cGX8o7NLteNAX59BzZ3da1s
DbWqPMELHiZ82TXnWuCMj6BHnv7hjlZHV6vF0Fyw10UrDorvKopTdCRsBUslbdKsghZTa1wF
u12bP0+uTfHXei8cRja9ga4ZcdGS+NpLEf3zVvvxjI7fNFJtaCMbXMBp8bhoycnqdezzHBuX
XBQuNlX78P869iyNi5ZsCW42OFNsXuEN1FTNtDEaqeQX/Y2q85/kw6foa/bA5oo829TA7ekL
mi3xOvjpdug3SLwHCi/9PNbQiYMdm7y2bWP0RPIErxB45cqyzt+6Z4IEPTL2l61z5WbCGlFU
qANfXxLvceO0PEdHInm7REejKqPt6nHRkk7Am/asKTav0d3um9M4yBugb/Sq0d1L3+ift9qP
Z2x0YwsRIfIa84Ad+L62EPcxySYKcRyHxjyowI5cftGKtbkxWp5jw/F6JKahcIk0LnnLuzXy
Lt1/TzvoEHxgsw+MFXTF2KHpuq7gB8aBzVV2MXcA2jwc2NTvr7uaLAP7/g5s7vr2SNVCg1IO
8BJtd9MNeAY10MMUjd64Fwu/DDTZ4HXRCm3Xb2xZpuhIfNOltirVIowO1HYrDvJqvwnmnVyc
4nu+3kyZySq6OH7RmhHeG/+9M6nhER3emkX3XBs0BI1BiouWtNBd7Yo+JtnUrRYZfejrlBU9
qPGLVkjVyx/O5yQbf4VX882QdCVWePR9rhb5lne/j/8eg1ZcOzRX4/WtDDR+c8cmH+FtImg6
745NV3mGnsCf4NRv0G8qVbACc2CTV9g2LWAN9AQv0XnXhRU+gxr4URiAbjSqNuMqMdIL2++t
6A28O6SdoyMbucjTQcUaF3hQYsni3KWlTS5OBJ9JFem+kRFc561JS7vReXxGNTyiEx28NqpQ
KWZjwIlcS1yjb9pQ59jUMIgIs0eVOjoq81Y4HN3aLM+Roc1XRRpFi7oM0NGbJjNB3jLve933
rIAFvAOb3X1X0QrUC5r74n+ZX8CtTH3Jt/d0mBf0tzuwqd8fh+UfaNHygubKzrDBx559O3SB
argb5OUznYGfWOa3rZB1cx1UBrfkOd7rFvw5MuSCrlPV3qgpKzrHu0bQXZrVfU6ykejADx/B
IUUbodZ7cx34D6z3+MxmeLo2XP1bMisaq5TrvXfF5mOSTdn8Piut+C+SuhL4lIqrlizOjaKb
olO31uTV3ukvoY4GPk6GmrwV3W9hvidgdtYOzT6X7QV73u3Q7HNZQR1uDmy2rLMK5nkc2HRZ
h/axHNjsnsDxwFZ5LLLe0ys15G/cM4+Bn5jk+46CRnNl19W4KqbtdE3DXSs3b9wpNuTbNxml
8rDqIgK2VV4yyDuuT8rm2MhG2qtoV1+dXtHkjzWRtzeDvHzGMTxcGyqug5hFm6sItCD05dZ7
c2zCb8UoDMmry27C1qYssay8NWmZYxMmLaX0OnyDUlHLmbjoLe3+bWmX77yn4E7kwGYX60jA
kZ4Dm12us4HOZO/YbF3HBurOA5tfrsOrddnFOgL9/nfoVxfrzjAGfhiUwUMiHiqqXOAMRVuT
F6bj5j07xSaqdWOMPnrrvcB+vV9erJsiE3W3ob21MIfG50HWjMjeCbozjOHp0sQkQ2uF1Ao4
D5JguzfHJrRZq0bOplZpuO3elxfrpui4OFN/+fi+U803WujE77tYt0LRfVOxzlDhdGCzy3XD
wEfegc0u2KnC9TqH5so6f0GDB287NFfUydbB0tEOzS7VEVgo3qErZN2N4x6fOQz8NCODerdw
e2YCvcl1iSts9CNdv22n2NBWi1L4oBH3itaC6hrrkxtZN0VGttqLtqLdxR14oBzXfLWqO0MY
nq7McOUQIy09HAR/mzLdFJswU26N/SJ1Rgw+pBaZKctlsvXnJJ26aa+jxLxyNAKhLYI6dat9
t6rL02z//z//73/9v//zH3VFK+WT2UNs6jBZBoESaMGTeIHW/g63QSvR4A7OsuzYXKUdzrTo
LMaOzVbaDN9mAU1dXYrefbCW8YKmfndaN27gS/nA5u4ERjTQYp/vwC54kNR6M8RyxmPws9QC
6dJbFddz2sG2urhoARu53Dt8TLLhzYnUFt92EQMVKq9JG7abAdI5NrTx6C7oag8jGvA5tyi5
5NI28eeN9uMZmbKxSGtKxYZZAQs4cdUCOnQzqjxLx7iYxPlDrWrgNjWuWkFHr85SPqfpqDYr
pNRGGQKWUf2qdxl1lbT7lmHlsg0CLUwPbLbC69XAzvUdm63w4Hi/A5ur8XSTAY5TH9hcleev
KwUrfC9o6qeTunW0BeLArtB4d8MGZ04GPwsv0NLCNa2NoQNuelpRvXaNd+01OMfG5VoptTgP
GtYYTf1YYRLij5drP5o5Nn5XW5zEttKZK1jooiX6OwILf3Wn/XjGxuWaDi1KWka0pWKL41et
6OQsv77VHtMxjkp3bI2sNPBcyq9aoVlffs/399pjOjr8QdBZm9904HM3LnprvDUaL7fA010Q
oRFrBza7A7KCrhk7NFva9QYa+RzYbGlnDZxrObC50q5tIuA49YHNFncG+mjs0AXygetNVeUM
o+CneQe9jCL+9jOBHdPmkuT/VdrZtbnvHBveWMz/+JOoSAGVt1+0pHx3yeZzkk1Iu956bVL7
GAWd8V0k7W42EWcWxSM25ZXh0qjVymrok7EsSXGheqm7P6bp+MoI1V6klcFgw21ctYJO/+W9
9piOFtFmZioqBtbxy18aUPePMRsMG1y0O+LAZks8tICyQ3MlnoXJNjjismNzJZ5t5eU5j3x9
OzZX4tlGClZnD2yuxBO/48GTmQO7ROTdVFXOPAp+lnmg4R9rXeRJL9SKA2e5tEv7mCTDfh8o
i3BU8RS8u3nJrG/tdnUM+DnJhvxrdi1kzdQGo7vZTZdEEF+y+Xmj/XjGxtUaNWaXJ1TKaGA+
tF+14lCztpve20k6bdTWyB88Si6M0CPnFZUGYr5qbvicpqNSC9VRVNtQ8L1aJh8Eb433nU6D
3XfC6MnTjs3VddFxBYZJHNhcZaeb71Th4eXApq5v7VtRrPduh+aubnMpDntcv7C5n8+1WkFT
pnfsinPZm2QuPrMo+GHcgapW6V1aR5/nftGSnJC74t0kG/MboRWjJiHvQDZLNLfxTe/dJBvt
xYppIRlo3OXsAMK/HmTexA3yGUXxiI1LNGOtY4iWiBpDXVyWhMBdd6t9TNMJBVTF3ysxJybw
SeaKY2a+c5CepVNdbrPTGczo+ONsovRb2P0GhoN9MwFL6Ac2u++uwq6kOzb7cJYKmhW2Y7P1
nb8JwcPjHZu7vhYHwqCC2rG5n0+30cHRmQO7pHJ3fWgmZwqFPAs6qI27mT/ZW8OnK5awaZcq
4mOajVXWUQuLuW5F+whXRGzXfvPWnWXTSoTASQnPSrBMHBctUXi/vNN+PGPjWq1Hjyf7XiLa
tFENwStqXXRTJZ6l4wLPN0XM1dR/P/B55grBypfT2Z/zdDh8qlzbEcd+AqUzVVh9K7zv9B3s
W0Nb7g9sdulOGH3179js0p3vUEHptGPTS3cVnerdsdnFu95QX8kdm128aw30kz6wX1y8kzOP
Qp6FBFRVLqUN6xGv8bsU72bZmL/2nJBL6cHgmX5C8W6WjXaqUsKRIHKLc4t3V2x+3mk/nrGJ
8Yioc/GodQzGT2WXRNlddjN8TNPxvUOobqfjG3Nweq6sOTNnvYpN/JynU/z3X0hdrjaDld27
drdA2X1L7W5spGCn9YHNrt2JomezOza7doc2yuzQXHk3ttLRlLodm125Gw8qdyO9chdLhp7N
7tgl8u76xEzOSAp5FhTgkjHcxzqTCjwzuyI+trZyU06ZZGOlN1cPSiwdHMtcVrm7bnafZdNq
EWlq2kUUPTdf4RV6X7k7IykesYnKncUtxk0GPJS5qG53UyKeJOMayBfF90Sj+3cF96gtOWi+
jPj+nKfDStXM9Z3F3faPbrljWN09Ma3FvtMVVbI/2IdPOxiTfWBz3/nhoIVqkh2bfloMa7od
m7q+JL5mqAHtjk39/rSGrRo4yrtjUz8fW8TjgJMEO3aF5rzxaZEzNUOeRRloGTyGv6MiTD7Z
p+Xai2+OTXjxFQpREz3rA3RN35bsB+zGkHiODfljIZQNDesuCcAf60YrZFq5ic6RMzTjEZuw
1es0KrfIuoZD3VYMWrtKuyrBfUyzMZJW/FfTqFYWNNFkRfWaSK9nimbpKFksTLHCr/3G+6w4
V919mxUf6NZyYLNbsgpsxbdjs0VeBztnd2i2xOuGNrTt2GyJ1xQ8lT2wuRKvR4809tY9sEsk
3rVfi5wJGvIs10BMo9fbGil1NK1qkd3yzanxFBveSguB1yPulsCuJl6Sdngv8abYhMRz9U1N
1NdIwcT1bYnp47jMVP55p/14xibUWrg+imjrzLjf8gqNV278WmbpmK+OizzfTbAQp/otl0uj
xM9pOiqu7cgfpNIGOgrwtxYW/xFefP6khL34ApvelYWGjr6g6dpOQAOtA5ur7nTjAmZNH9hc
def/T0zaOTBd16Gl4wP71aW7M6pBnsVoaCGTEWOWRKin0KT91gOPljk2HEqolz7ib1erqEfL
CiXU7do3Y45NSLTRmpTaSQgM5V5UuquXa/PzTvvxjE2JxwdJDdPHIIXRWeTDR3JzYDxJp7VR
h6+MdLYCZhH4VUuaG/vV/u5zmo5ETrT4N0Wjo/n0ftUUnbeu+318+OAT2gOb3pUFpiHt0Fx5
Z5sS+PEObK6886+kgz/lA5st7waDR1IHNvXzSdlKB0vHB/arRd6Z1SBPczTUGo3RK3VBu+i+
/nx2ig1vNcYjuvTCQxgrRcZFX128m2ITIs9cfffXpARqXbBK5N0MF51JDY/YhFwLhzdu1e+4
gudorDjRrDd+LbN0mplr1khatl4InWBZYrZM5aZ4N0lHut9jo5A0Vob9WuQdpPHvz3ykG/EJ
OD+2Q3NlXdiPorpux+YKu7DWA1+TL2jq2rqU7KBPwg7NluyGbikObHbT58B7Pseaul29OSU7
MxrkWX5GFXgcvq5pTrs1ZplkYU7D0Kn5NXMdJlf6+nOahrIMePh4RYhJ9Pb/6pb68YzFa1y3
0vCHrcTsQO647rjZJkzSiTH3qqXYEOug68+icV26nLb5nKYjQ6uvulFlfZVnMTrvoIwF2u27
vPYI9Jk/sNlHr2IVNOzYsdmHr/4QAx/KOzZXxvWtMfj9Hdjc9e1bKWhQ247Nvv+inAW3JtZF
KbdXXeD+3j2jGORZSkbVqq0Sqf+E0VZQv2gBm1tDlkk2xq53exyNET5/vKLd6V7ZTbJR5ghS
LeS0YLm9ROGV+ss77cczNjGxSzxKiXO+mHZFFd6SctZlL9rHNB016dzH4MLCFRWsa7z2xk11
bpZOGSQaszqNCCwFvx1Z/kyvPWpgB8SBTa/PDVA6Hdj0+lwz2GsvsNnSrhawBnZg02t04DHg
Dv37K3R3PntnEIM8DsnolUcPK1g4/WyRhfJNZ90kGytWxEyVKprtl1Gwm2SjXDrV0aq66oZ9
9pbIupuQDDljGB6xiRKc+u6BOXoeBRzOWSTrbgt3k3RUpVo38+dib2Agy6LCXe03dt2TdGS8
LKGlNn+Rgxvqd+HuDzba6/5SAh2EDmzu+1W3Cp++7tjswh1XPCQjsPmFO3Dy6cBmF+788QkX
7gKbff+hzey6Zuay0vU7V88QBn0YkCEuhBr71qxoQedhl5zD3hXtZtkYWR0kry4n0Kg3oWg3
y0Z9WcilQzjtgQ/iNbnDt0U7PSMYHrEJnVZivJelMGwXtEjdsV6ru1k6EWrbzMTv49FBQ9Wy
xuP6LgJtmk6tOlyr1j6agnv+v7Vo9yVGe+gZz5rznWXzHPlWewPzMdih2RWd1tA50x2brTgF
HUQ4sKmrGzoI7S86sKnfn9aNCRw0ObCpn4/bNgw8UDmwCx4lXK9dWPTMh9CH+RBkfvOVFrbI
4O99Td3qdpBjjg1vlbiFV1jMPoAH33HREtV5Pa07x4Y2UhdoUYZTrqDPR1y0QnVeauifd9qP
Z2zCT0W1aIzacDe0eW5FZAAxX7H5mGbj+5tijahGjyNaglviwfIaELy/0x6zUVeyg2yo0+qg
EXFc9Tdqzn+S0Z6BXiI7NLuoo6hZ04HNlngdzNveodkCjwdYUjyw2QKvCWjyeGBzBZ5tAzQc
3aFLioo3L90zH0Kf5UNoMQsT5R5Heck+yjdFxSk24ZfXqKrUyHYFb26/aEUSya28m2Lzknda
pI3SVHLlXb1snft5p/14xibk3ajNhbeqyGip+o74eo5olo5x8V2RDOlNDR6OWCLw5LLk+zlN
JwrYQ2s0VlnFi4pvk71FAi/dZE8Id2EJbK62k60P8O1/YPO1HRqEvmOz1V0kcsEH7jX5QDa8
VcCdxQ5N13agyUcglxTubo6LzxQGfZaQIS7oYnhvUFQgUPvkFWzubPbm2PDGtVd/zZbKRTv2
tuUlJh/11bd69badYhMiTYb5lqUw+hReJuyuAzL0zGB4RCZc9sTiqLhJNwbjPuOqFXRuDFhm
6TTrLoAiXaYN13aZBixMN5W7SToSHYBsroGHMZiUE1e9hd0iYfctLnvsmg08xT6wufqubQN3
7BjJ6jOc8xRtt9uxuequbQSKzx2aq+3atht3IOJux+aqu7ERakF9YL9a4Z0hDPowIGO0NkoZ
0aoFElplpHx3NDvFJuzyhhQaTVq8gVEj5RVs+qUo+pxk42qNWZvLk0HFQGOTuGiJxLu2/tEz
guERm/DYk0FORtXFN/heWWakfHM2O0mnuRIqVGLGundwGGeZkfIv77XHdKQN3000VuLq99zb
SDlN4uV77JUKTske2FxZR1sXVNft2Fxhp1sr4A71wKaub/U1g8uKOzZdtito4nBgs7s+B4PB
8Ad2xbHszSSvnjkM+iwjo2p44/feoiEK9txbIVRvZz0m2RiZiGmlWkl/n1mPSTYx9qpsrlVH
BYOKEiZ59UxheMTmNcnbKcYiQkWAu4hVsx53x7KTdFx0u7Yz30qUUXELviWnzOU6I2OWTiQG
im+JrPkeD/zpvCd5/2gLPkWTag5s9sGsEerTsmOzD2ZrA3tlDmy2whPQ1H2H5q6uuWZTUN/t
2Oy7z19W8N0X2BX6zm6mKs4IBn0Wj1FfGVuNrZaK5rkkzPJOsvGfuVrpZsUfSGjYxxJ91y+L
XZ/TbJRKOLxR6w2dcKuTre5PZnnPAIZHbELfuaoLt0f/p4EmRxmzvJN01HQ4j1GlChwnsWaU
V2+67mbZlCaRODxc5MEn53/nJO/fbr/HAu7jD2x24W4o2i+2Y7MLdzrAccoDmyvrXAwZKJwO
bHbhrnfwTPbAphfu0HbPF/Sry3ZnKoM+jMhQkkJUCinD0bZf7qs8y8aIubhSbWqksKxb03N3
U7abZKNMYxgPq6yaOcjst8PNieyZzfCITcg6V0GVhNhiBBiVdUuOMC9V6sc0HVUdrfriuORW
xlZnWdnul/faYzoSmSatubSrVMHn7jv17A824BsbtQEa8O3Y3PdrTHCiB7M7NrtsR6gAOLDZ
ZTtu4Nj7gc1d3zDVAwcqDmx24a6DlnU7dIW+o+tAeT2zGfRhbgYZ99oi0nLAGWJ1RaHrVt9N
sjH/HbXzL1QRfX3ZbpKNEnWJhkiXRDCbNWW7O313JjM8YhNKjczCLtoXqQw0mWGJvqO78Z1J
OupyNX413FsrubkZr2nW+3vtOZ3CytyKWIuxin/0sSx9hQUfeIS34vTukUwBFcqCR+QCLfxN
toBtgEd0Bza70lkq6hqzY9OVcEM7vnZs6vpywyvZBzb1+1N/pzfQuPDApn4+HpsU8PdxYBc8
TLjeaOEz0EKfhAzEsIJEN7t/QmtoeMqSCYf76ZMpNrzVNlppJk2KgfUnv2iFc8zLuP9Kn0yu
zf9YGe4Ym7hoidq6OcI+4ywesYkDTwmv4yKl+O4LNp9bMX1S2nWG3CwdV/TSSPqwEg7OudaA
v7zXnq+O+g9mSBVlbeAmf7Z0+7tr4X+SNWATsFv4wGbLvF4JLIjt2GyZ1/3nDxvIODZX5o2t
MDjpcWBzZR5t2sED9wOb+vmk+j2FPdp36BKRd32g3c5ci/Yka4A2rmxhVhKjZODtSkvmPl3k
XVeh5ti4XnOVJ9Zedocgm1Xuz5fl28/ptRHzu5p6sTZAUeTXLElgq9fugO0MtXhEJlQEKRfp
ZJXQEbNFCWylXfX3fkzTMRF/JHKPcN0Gzn/HVSv6FOm6tj69OsP3E8OMxLgSfDz/Ps9epPGS
3QEjEAPstjuw2d1idaBxcjs2Xdz1B+Kuf4O4Aw/bd2iutIuqIfhCO7DZ0s7AVoodukTaXVW8
/I17hke0Z+ERXGshG5W5oU7Wq6TdzQHjHBvemK0Vcl0XxRXQl3tb4dtU7bJE9Dm9Nv4NsbZW
uwtW0Ft4lbbr18NO7QyPeMQm/EkaWWEeMVLTYQu6JWfZN+4xs3SaRe6x6zoi9mXKdI+5GzGe
Xp0xhNQfBr7VEzCS6m89y/5HGQSC79gdmi3w4gcGzwM4Nlfg2dYq6iOzY3PbUXkjsMlmh+YK
vPhGUIG3Y3MFnmwGjjvs0BXNinLty9vO+Ij2LD5ClI36YH9fFcNGJeOirxZ4U2z8LjX/lUeQ
6wjditoDLon2uDxu/pxeG5UyWMh6UXQzQWvygmu/Kd6d4RGP2MRRa6/U4gBw0ABPXWbTwf6V
zl3xbpJOJK60TsxVyytSERN4C56i8f/81b32fHW4hU8I9WZV5B3tkekhk/va71sVbHu1Q3NF
XfX9NuiXdWBzRZ261EAjeXds6upGN6KCgXIHNnd9w6gb/P4ObO7nc602QGulA7ukcncj7M70
iPYw2cNftiXiOAsTugvxixawuZtCmWXjGpVaOAS6TEVN1xdNoVz2qn1Os9Fu/qc31WpgA0Cd
PCj7X+YxN5W7MzziEZviu4EeITJaxOnAx5hz4REPzAFn6Wgr4bMSC08Mh/IumTK+7ov8nKdT
JXZ3Wlx1Ky673/YxC4Tdd5kDGlg4ObDZTXcF3s3u2OxzWf8Z4uaAfcWU7BOFx1spqELZsbnr
aw9S+Sw/lY90GxXtUtuxSxTe9fRnO9Mj2sNkD6pKptIi7wxN5V2h9+8V3iQbI7auvdWwKoEV
3go2/bIQ+TnNJtakh3W41M6omXVbknbWr/Of25kd8YhNnLKybxSLsG8p0LmkRWezTNezFbN0
1ITY9ZAvUq/w2PSSOWPmmz6AWTqugtWi9dZ/l/jZ7NTm6K3wvtcgUNBgnQObXbyTZmBxZ8dm
F+/C4hQ2CGwrZrSfSLu6DTQU7cCmF+/Q7+/AphfvwJ/HDv3q0t2ZHdGeZUdIrXXUppVEwFm5
RaW7Vm6E3SQb13NqJK7s6mio3eHXl+4m2WgfhZ2HCSv4qFtVutMbYXcmRzxiE6U7doXVo7kT
jpApS47/b6ZMP6bpqDbR0iuPMCeFDzGXVCLvNhGzdGqJuDahHhnDb+fnTGH3TaW7jr7ADmx2
6U4YNZDbsdmlOxb0FbNjs0t3yqBB4IHNXd++VQWb/F/QbPVJ6FPwwK7Qd3RtVdHO7Ij2LDtC
/P0UViJGrOABk1+0YgyhlWtTlFk2RhQW0MNaGWiozqLC3eUYwuc0m/B3Ma5R9mVwhtEvWuEi
UvvVWebPO+3HMzau1HrVLv6nR94ZKu++OtZjlo3a62jW1VB9ULZbE0L3yzvtOZuYpDCz2iLi
FC7b/ZUdd/wV9oDgd7riJfsnG/EJ6JBxYHPf+eGsAL5UDmy64oSzgnds6vqybhUd4Tmwqd+f
VtdpYLvngU39fGwbow4yB3aJ5rxp0jqDLdqTsAFyta7CvTSKaCx0WHSJR+mdEd8cG/+hi4jV
qsOcFOiTuCYZr9vNnMfk2tDgYo3N9c0w1IhvReqja85ry8d2xlo8YhOjor4o3FptUSeFZdqK
s28q16Ejs3SMtHWWzmPsG45MI76rHcHnNB2lUYcNtt4GGpb1Piz+8434+sBu3R2afWw3OtjU
fWCzRV7soGGnFlmRe/dM5HVWcNpxx2aLPGXQBvLA5oq8vhnqRn5gFwiJOm4Ojs90i/YkccD1
WnhnDG2DpYGFRVqTPCKXOXkfk2x4K9pDELVIQUZ9+JaM49hldtnn9NJwIR4qRL0OcPwuLlqi
8W4cH89oi0dsQq2py7waf4S/eKjgf5XibsxaJulYZG1xsxHWj2Dy+iKNV+yX99rz1RGjKhFC
VGGHjFmbxLfG+3YjPopUI9CIb8dmy7sG/qZ2aLq4I7B5/gXNlXa2oQfGOzRX2Ok2GPVX3rHZ
wq4rGONyYJdU7268M86ohvYwRoNqKa7sxNUQoy4tK37n9y4tU2x4Y4qRxDIGdwN76OKiFcpO
btrvJ9eGy+iFijYrqJ/nGotEV3Y3ho9nUMMjNtHbR2YabQ+kBR/mXdERWO86AifpNLNO5KQi
SwM9AF/RFkSvPcv9rfZ8cfwW8y0RWWuM+hvNzuG8hd3v48JXVbEHy4HN7stiBTfoBzZX4Zlv
bQQs3+3YXI03/N0Glj8PbK7Ka1tp4MDxgU39fOJPONTH8AVdovGue/HtTGqwZ0kNFMlVbVQa
vaLz3dsKe5zbE9o5NuGnHt5Mps1fvAOOSluxNnfVu9m14UJx4Dx4EJyQvqp6d10mtjOo4RGb
EATUeyeptfQOvlmWWS1f14ln6TST2ljYwlQHtPVeZrV8vZ+YXp3uT1DWMqz4cwBu2nzHaPz7
Ux/JTny2jQaWJw5srrCjTQsejxbYXGEX/nrg4+vApq5v+BOi8wovaLZs7wVsADmw2WXjUtBh
8h27RNhdN+HbmdNgT7zzfWWbaR8UBquE7kM2XmFK/Epju3rbTrKx2szv1RpSCGazZNzDLmMa
PqfZKBtbZOs0IXD0qa6xWC56PVhkZ0rDIzYuAkSpKnMdWruivWprxnkvZ3E+pumo9m4j5nk7
G9glvGicl27aPKfplCJ9jOj8oIYfmr8zNBYIu+9y4uugnceBzX7DCqEnFjs2+2g2ptdgJz5d
EfDxzGuZUbuRFzR3dX3HAPZ87tDse6+DRbsdukTbXTe72xnRYE9s812m9bAQ8wd6tSaoky+v
OGa+8+CbZRPWe9267+Q6EXbvLLJqudV2k2wiaaJX6mGSCI5VLNJ2tV+7PdoZ0PCITai00cqg
COEa/q+pLss3s7yzdPz2rS68rcgoAzZZXjLLe+PUMs3mVUmNZGLYW/Rt1PJnOvCxYA/GHZpe
sBto3/eOzS7YaUMF3Y7NLthFyABasQtsdsnOHjig2BIHlIclO7Qge2C/umR3BjTYs4AGbs1f
TK7plA124FtUsrt5106yseq6IaJorApqf7moZMfXTVCzbFRIo4pSSx2Gslkj68ZNye6MZ3jE
poQX0JBKWlp4AqE5sSvMgJzOL2+1x3RUuYXXTCi7Vx71F44ewLPMn/OrM5r57q7aUHQz/a7Y
/dEGfIPAVrYDm/2CHYxmK+zY7IodM2rev2OzK3aEJga/oLmr27fKoH3hgc39fLpVtN75gi4R
d9fDi3ZmM9izbAZuIkX80a7h64CKuxWDpbfibpKNUVi6tGZ9DDhpYpH93k3z0yQb5R4Kwl+3
XTvKZpG4uzbdsTOZ4RGbqNmpRLxyl9YrWDdYVLMju87NmKWjpkVdCA2X9TxQrbqkaHeXjDZN
p7I20uZLNKjB6u6vrNp9iQEf+rZY86pYNuWRbsHHBZzxPLC5b33e0DzeQGbrTergpzuwqWvL
fWO0IHtgU78/rRvYAfhCpn42tq0M0FrxwC7Rm9cjlXZGRtgTG3/aWI0pju5KcaWGDg98tfXe
HBveaq8umweZMdocHBetKCZedjN+Tq+N04hT1SaE9svFvnCJ3LyeErczL+IRmfD9aP52KF2p
yAOD5BXFN9brMfFZOsZWdMgY2ir6FPWrVmwGLp33/hsAAP//7F3bruy4bvyiCCIpUtIPbCBr
fUWAvCYB8v8PIdv2BJgDa8oaLe299vTcznkoz3S13VaJIqv+/1F7fndin9bD/cd/P2BE+9t5
77s775ErNtCA98TurumogN5nJ3a3wmulwBXFwO5VeDUxaAp6QHfruwpa7xzQ3QqvNzCl6cQu
UXiDgcorNKI+sfJ3RRC9hdWFkTHaNxcXLVF4gy7AKTaScs29565cGoPdEHHRki7AwRHe7L3R
aGeUGjUrtDchrXjLucQbDIlfoRGP2ISI8E1s6bmFJzGsIRbs3IbeyrNsKoeNoLkENy7wgMcS
3717j/XP+Zvju0d/vfiWglTAEf63wvvGvnu1gqeJJ3b3YXFDx4tP7HZpJ6A0PrF7pZ2lDrvH
Hdi94k5T7WAzwIndK+9aogKaVJ3YJfJu0Hp/5TPUh9kZfm9Ns0aDFqzuFph/DM335shI8p+R
67tCTDUTuHNZYlfn/73BTOXkrWEz3zJXypYzbKvMK6w/Mv3lg/bjGZto6zMX9JWImCs8R7Bm
fndkzDJJx6r0xhFAx631rcYs930jn/N3x3LVbJK1d4bNBOc2rW959+u47/mmHlR5B3avyqsp
ZzQh7cDuVXk1ImfAI9oDu1vlKerScmL3qjxLvkkGPZYP7F6V15OrFPD7O7ArVJ4MOvGvhIb6
LKEhtxKLLpn1AkuJFSPx42PaKTbi+rNTY/GFKleQjawpSdYykHmT94aVoiRpYqWDbu1x0QqZ
Nxoav/IZHrGJmQ/rRFZyz65a4VHeFQebUgZVvEk6VjkmjCpJ979Q1bpE5o1MlqfvTuVs3Zr/
KitugP32WP77Mx+b7fdaygQOkJ3YvcqOUwNL/Ad0r64LQz15YL63wvTiwd2lnqyB1bsTu/fu
2oPQO9sfeseSYrlFGz8Du0TXDZrwr3yG+sQ0P8a0s2uGzN24gn22tOQAcGzRMsmmcvMXke9C
GjEou3dYtEyyUSm1ZmVRIkbtc+YOzP5F1w0aPa94hkdswls8Z2Iy5lwJHhddYRLBIncNax/T
dKLtrrwyxOLnA497LJleyYPT2dm74zsIjVOu0oqCP533MO83tt/ryR9ccJj3wO4+nzU0gfnE
7j6f9d8/7L7Xt3u19I6aUx/Y3XXZjobKntjtTx+hgz0Hdsnp7P04b7uyGdoTv/wwzm454m57
LwaPjC5RqyN9N8vG9Z3GEqUx/7pV37V6d6D5Oc1GOedGLu4segpRfbeiXW10PNuuZIZHbKIC
18yFEKkSt4qeZ645nh10AszS0ep6NXNuORQrLIiW1O36Xz5rz+lkJv+apPl+osNV1be+W6Dv
tpvwaQNTeE7s7sJdf2DD13+GDR+jU7MHdq+0y6lmbLt5QHcLOzLwlOPEbi/cCbjtObELxAMN
CnftymZoD3MzRFRZqGVCp1jiogVsLN8tTx/TbGrpXViq/1Uz7K284NkemvDNstHiqi6X2rOB
LairYjPofnynXcEMj8i4QgtzxFYtjjAbaP8Vp7grdN0gNmOWjoaxa1bfQ8TjBrsRr6jbZbq3
BJq+O519h6dWyJT1nYe2U9f9rLqdgs2vJ3bvAqupZHSu4sDurtsJOht2YvfKOw7rOlQd04pK
zTMTPjbchC+wu+t2raB1xQO75Fz23q2iXfEM7WF0hiq5+uyuIQg8CN9Rt5tkUyUrN22FegUX
qR11u0k2yrn10nKPoHnYY3lF3e515DB+0n48YxMVuJB3LNZdFYFydVHdbhSdMUtHQ6la5pJL
loaWIddkZ9yG1n3O08mvoRfz/43S3T/aho+/vQ3fI6ECapQFL8kFavhnmQN21D7mwO4udWZD
u9gO7HYtnNFjtAO7t0sxl2SoB/GB3fr9KfsyCKrNE7v18xVKxODzd2JXFDtvbUpco1ypFu1J
0oClM8K+RNs5+GL0i1acyY+mT+bYxCCJZfXlPPf8slLDpk/WmFLfdynOsWEXtlSYu2n4eoAv
u0Wn2DLol7gyLR6xoVSambbWyLiA+do0WU77MxsbFDun2ITdn5KaWFMRNBspL6mrM99uIz+n
6fgGkilrJaoVPfSY1fa/uhj+J5kEMuoIeWJ3q7wGBwUf2N0qrxN44H5iN6u8WN/BZsULvFfn
laQVPDQ+sXt1XkwQgR0fL+gKlaeDmucVb9GeRA5Y4s7UTH0l1AI+D3HRiprn7VTuxySbEGzm
oqi2Gqey8IzxklmUW/fkz0k2nKxHUgc36Qyez3OqC1x+xiLvyrZ4RCb0mhgbldqIwU7FVSLv
9qjgY5KNy7Vw+clxTE8En8/XJT4yt+0Gn9NsrGSXjhaZ4YxaqMdVb423RuNttgmUJA3rZjug
u7vF/CkE97QHdre0awXsTT6xe6UduR7PaAvUCd4r7Voq6Nzrid0r7SyRgDaBJ3aBgOA+KOFd
WRLticG/JctCvuTmqmj7SlyzQtvdeh5+TJKRcMGQYtpzrwaeZ8ukC8aftd1tlehzko3rNBd1
YY0UBr3gHAqvSZLIt82XfzxoP56xORpjW1X/M6M2w2saY5lvY9g+JtlEAzdx45yjjtcyepy9
RHnfJyB/TtNRlWhiyNKtKxjIOBvC8lZ3v45LYFXQhe/E7pZ5HS1Andi9Mq8mRVuVT+xmmccJ
9Q55Qbd+e0YpV3Ak5cTuPkWWDh6cndivPqW9wiTaE4d/SyWSMYyp+aJl2FJlSww+xhpvik3I
NW1UWtdaaoc13opxoUb3QR9zbDh1/5fmkN5KaM9iXPTVGu/KknjExuVaKT26+0wpE1rAW/G7
4WyDAt4Umwj66NyEangwoZvRZUEfgwreJB1jda3aRVwcKqMjKfYO+vjbGm+/R6AY2D92Yvfq
umijR108DuxeXacpek1gl0DHbr2/0qMnEXYvzktc7p4NG4uB78sTu/fzldQVnZY5sCuUXRsc
mF1BEu1ZkETpJeIKmKQK2HfDSw7MxsPGU2xi2Lia9Vx89cM9D5cMG7fbCtHnNBvtUlvV6O3r
uEvg1x5m/vGk/XjGJqeWI++sSI4BXXAT4VctcQnUOy30MU1HTV3SuejWagTuIla5yPz1s/ac
Dmm3XMSlKmWBh2umltW3tPsFXAKbv8VhgVd26ztOBO4vDujuw1ky0MHwxO5Wd9rRBLcDu/fu
hjkR2ld5YPd+PvOdLjh9dGKX1O0G1ZQrP6I9y48oJQIXyEwyVdBaaMkAqP9HBydmU2xcqFmt
/mOqJgKSoSXdUC7A7oZzP6fJWDGNfN6s/ic6OG1Loj1G4u4Kj3jEJmSaabznjLiDB81+0YpR
EbktQn5Ms9HWpUhRytkY3OblRcq7DrTdLJ3Sesm+fayV0XXrfTT7PR0CGW0UPbG7y3auJOGy
XWB3l+2042W7wO69v5Jgd9wTu/f+9iSEWgQd2N3CDu2CCuQSUTew473CI9oTQ39OtZcS/sLi
O3YCN0l+0YrD2NFaO8WGUnM6PVfJWdFRF79oyWFsGxzGTrJxHq6B/B+kr3P4bXY4ruoGBjJX
dMQjNjn1LL1rV/+dGpjFGBetaLjTwcjsJBvLLb+qXFq7wTEltqIAWWjQ2zlJR33f7qquFWG/
OV8bU/JWdb+AP2BLHY0ZPLG7a3YFPUF6QXfX7CSDNZ0Tu/fu9lQEdIE6sVu/P5FEhN3dA7r3
01FiNFPmxK4Qd7euYP/ukuYUEP2Jm7+kLBxTxq27ugP5+DUrtF2/13ZzZDjFYIhpGL2jm4I1
XNrtQfnnJBdKnXqvOVuMycJxKytCvZluQ8H+eMx+PGWT/V/KrhtysVZQNnmFFKLBWewcm8jU
tcpdrIe1JhzEu6QF0v7ySXvORrpyiYBAyiqwTv0t52TlK4wBwc6QFT1F39iAD92NH9C9UtMV
BoPDpyd2t9hkBZuXX9Ct95Zy5NaCR04Hduu3pxF1Cr7GT+xesVlTY9C26MQuqSTej3X0K82i
P4kY8F2O39qw/lD2/4dVEGIWZAGbkfneHJsY0qfci1qNgUrUloXWnA/fz1POseEkXJnCGtEl
DWNseM2w68iXpV9hFo/YUIxVc7MqvrMp6KtnyVg18yAheI7Na6yjWc4txlS4wKO7SyaR80Bw
TtJRUZOoWEukyKGCcy7W5lcXnP8s8z3QPO7E7tV4JfWKpskd2N0ar6Et5i/oZo1XUjV0svgE
71V5nKiBW4wTu1fl9VQyaA14YpeUFO97s/oVatGfBA34/oLYX+5Sc6aGTkv7RUtU3n166xwb
SS7xWHs3zgWdrY6Llqi8+4nKOTYh2MzX3ty51w6Ou/KacVei+/PifkVaPGITgi2HHuKoXIHt
24tUntw2z35Msgm9xkWrxWE+lYpOeCxReSODllk6qv6c9eJ/+M4CrGC/uwC/sf0eEWgvdmJ3
yzvtYE/Jid0u7xQ8tTqxmwVeT01ggXeA9wo8S6INdD85sLsFXhWwmfLELinjDYorV05Df5ah
oa4a1X/BLkEzWPiyJTkNvizeJ8rNsRFXN0JWtLXSewY7DpZIIhd494lyc2xcq2mV6Nak7os6
6s6yYtqe8+1B6x9P2o9nbChFlUiiLFn8JsHR1EsOwUfHxlNs4ti4UYTrlpatgTXWRefGnAcC
b5JOmF6rau7U6dVwCNGZ8zV6C7xfxYGPU20ZW2VP7F6d5yt7aeCL78Du1Xk1gek5L+RejUeU
Mty0eIL3aryaGM2uPLFbP1/hcP0DB2YO7AqNd1so8pX3SmnozxI0fNVlK68sV/8WQY23YuV1
jTco4k2xkcRarffoDuSGGvAtCXSuI4k3RSZ8G02ia7NkIbCuwktO0YcGfP1KaXjEJrz0XEA4
Fa49C1rDW1ORHMSkzbFxsdYp+yZFOndjRYtetmKSV/r9zMcsHc2xjXdlLzH0AdfwfsvM4N/d
gC+j4QAv6F5Rxymm/dFZj8DuFXVhqQfKkhO79e5KS01BXXdid4v2DjrSH9DdpeNsFdxSHNgF
ykHkLmDV19ornqE/i2cojcxXpiaRGItmby0xIrY8KKdMsaFUqcUBYPFNCPru8otWSNRa7sNv
Z9moVFHNzkRVsXtDkz1RD/xZ+pXO8IhNmO91qbkUbr0xeNC8ynxv1IA3SUctFw0TbymUDdZB
K8qq1Ac7iFk6maRVvzu+f0Br3nHVW9b9fVn3k0Z5LYOxGSd29wpbCqifTuzuw1n09CGQe7Vd
x0MfTuzee+vbBdQ15AXd3vVJ6GTPgV2i7Qa9UFcsQ38Wy1BEqPs2vTMpWGGOixaw0dGh7BSb
l6+JEpuFTzSa+rekFYpau4+8nWWj0uLsr1uhqmB5fYO2u1IZHrEJleb3JhfqvtPJYGbdIm33
ytgdP2qP6fjjW8LewPxvV/aoGFpxKiu3dD7n6RBrYWkll6zw3XmX7BZou+3me0JoWPuB3V60
Q83jTuzuop1v68Cz2AO7W9i1znC/WGD33t+aCmgke0C393sa6gJyYFecxOpgaPZKZejPEjPU
JIp2ZJVVUVuTFaUHslsXsY9JNuGpTJKrL07aW0U7upYUVFu/d7qdZaM15ktfR7EdbetYIx1e
Z6XjJ+3HMzbhj6xVNGpcJbu+Q4XdkjHTOijaTdLRMGmxYpXyk6LdkvGQ0VnsLJ3clGv3t0Bt
aJPOW9h9Y/+9yMEC5d0Lur1wUsCy04ndXbITBqcBTuzeu0upo+ruxO4u23X0+zuxu4+M2dA6
14Fdou8G0xRXMEN/lpmhlaqyf39igg4oLVmlXN/dJ5DOsYn8CzIjK6UWtGNjVWjGbRnyc5qN
+ZrbpFGNXGC0cLfEwXeo765chkdsXKn5/kHC+7q7vMN+On7RikPMUWjGLBttXRuFgUgjtOd2
UWjG0BRllo5olGiYciM0rOh3NUX5Ehc+QocXV8wtfmMfPt+7wEZ8gd277EsyBhMzTuxu2ckG
jp+c2K33N/z1WkPPoE7w1m8wHPYI1EEnduvnk5qkVtiNL7ArhOfIje/KjuhPDP19z9PU/O/I
4i3gExEWfgvYDN34pthIctlZOmuu2fXaTjO+eps89zlJhhP3qlmN41AfNPbkJGtGPAY7nCs5
4hGbcFzRxrnXFk7DqEvLGrfkv3zOHpIJvxVqrF1Ns+HHxUtcWsQGrQmTdMKkpfXSJVtRuFFz
zkH2V5ed/yQvvqzYL/GA7tV4muDd9ondrfEa6mR4YjdrvJIKgRLlAu/VeJwyarj8gu5VeM1X
H1DgvaBLCou3mQuazwSJ+D9P9B31Ho6xzK1n0APXdyRr3JZvR3gn2YSlnkgtzZdcamBb0yIf
vppvO/An2bjAa6VTJhdE3cBfaly0QEQMfPguNj+esXGxZl1f0+LRgbrThi/bbT/gJJmQahIx
GzW31mpBC3FrBN5t0fdzmo4W0pb9F+mvAmH42Pi3rCv+A2z4OPn7BLThO7C7j42bgjbGJ3a7
thO04fzAbtZ23b8U0Cb4Au/Vdpo6+p45sbvVnaLTvCd2Sf3utqyimS4N8SxNw5fc2rXUqHmB
9ls2uXPHLVom2UgSVw9Se3sFjILjTGsMZ1odrLpTbKKAF7OifncI9cyMa1YoonsXvovMj2dk
wlCv1VbNugtvsAOV1kSDDFz4Jtm8wts08icq15hS3unCR+22LXCaTjFTYgnL9Z7ByneeVN9v
fferuPBpYvCU9oDuFXk1ZdAi8IDulXg1qYLtLyd2r8Sj6NpFz5BP8F6JZ8kKWLU4sVs/X8m+
ZIEP4IldUsK7HbXUzJeMeBil0bVm7dZaBs3EbMkxILmsvF94p8hIYjZXRa1xlFbQI1peoVcH
R7STbEKtme9OzYpoBtu1Vh3R1rt65B8P2o9nbCKh2roLcJIsGYwapDVsWP/ySXvIxsWav3LK
OQGr4F4vrloi8W5HeqfplCqkytV8qVRwYvEt8b6nCx938Aaf2L3CjlMz8ODuxO6VdpoM9RB9
QbfeXWnJf8LwwWJg995dS2ENB9vwtc2VRY5oYHQk5cAu0A4it513muXSDs9CGkpttXSK/iQF
bZkW+fANvFom2YSlnvpPqZPLIAWtohd5tQx8+KbZaBjeunLo7PIO9SNeUVUdebVcbH48YxM+
fGyltDj1VQErBnHVCmF3W+z6mKaj2mrtLupKoQL+clb58LW798DnNJ0STt5WjaiTgQ5jbx++
b+3D1wj0uTuxu09nDZ09OrG7T2cJHZo9sXsVXk9Swft7Yvfe35aooOdRB3b781dQn+8Du0Th
Dc5my6UinmU0RKZYbea/ENePmCZa5MZnNGiJmmITYs0lkcTKmwvYXOIXLYlIu611fU6zUWZy
WdT8D4aPM1f8UscKr1wa4llEQ8tm5BIi99wyaHj09W5803R8g6Ixbh2GOhWms8RS53XmMn7W
ntPJpeccdVX/8YC9kW+F9z3d+ApomXRAdxfuuqHmYQd2d+FOOzpScWB3C7si4NvoxO4+cRd0
ZuHE7hZ2DI/0HNglwu7WQ0OzXuLhWYSGcpcurw4icJaR1/Tc2W3f/sckGZdoEZ5BlQv5CgWb
8S2YBqN2b5A2zUZVehNfcal0Q1Xqitm2sa7TSzk8TNCgsOHrJCFUwVfjqgSNcie6P6bpqJXw
48tazAo43r+ocsej/s5ZOi7qmlRupt1AF9S3rvvGZnxhcYZX7gK7d4HVVDJ6dndgd1fuGBZ4
B3bv/X25n8ItY4HdXbmTArbFn9jtz19B7fgO7AIVwfmur8vXXbtUxLMcDV8JWhhVmL/ewfM/
nnRZ/ReFN5iqmGITlbuYL61RRyP8bHaF+K7lTq9+TrNRI19wS20ioAcUrZEQAze+i8yPZ2TC
N7lEkJGUas4JPctc4rYsOhB4k3S0dsk57Jaz62/sUVsVo2F3UyKf83Q4IhJbV2lC4IstT1aJ
f7bA2yff/vc//vs//+e//o2y/7F1fcLeFrs1ESiHFryNFwjvn2FHqCURg96eJ3Z3S5oqWGs4
sbtltxTQRPzEbr2/LgXJ0O/vwG79/kzjnmHf34nd+/kksjzBz3dgF7xMiAYzpvWSdg+TNMSX
Wleq0sJWDdV2K4SqykAMTbEpKUc+GnUlQnOW45oVqvs+5GSSTFiAFuu1ikpuDXXeWeG7ynnk
VVMvYfcsRqOETaT/lV2uKly5WzEDyLnd3ZyPSTqU2H+NuRTLJRsYChIXLWFz60Y4zYaqRPaM
/3Jyq6iT0JyL588W3b9WVfUnmhHqKx0E1niB3V3aUjjp5MDu1nhdwdLgid2r8SzlCg7hndjd
GkoU9Pk6sVs/Xy1h0gpash/YFWfnt9kgvvS2S0g8S9NQadzErLTSwWaFVRpPByvvFBtJ1eUq
VSqdemF0nHlRU+RA5E2xKUkiKU2yVGsETviVVJaMM4+sL9ulI56FaZRajEtrLSKKwbVldmL2
z6fNMmiKnKLjCiekd209TiQKLIvWdDYMSquTbERDgjfprsBRxTq35r813s/2I6w9zEGxtesF
3S3tzNB5gwO7W9r5Nggu3wV2t7TDJ3Jt0UTuE2nXU8Nely/kXlknyRpYWjyxS0p3gxPzfkmH
Z/EO6mLOcgyIREwx+EK3JS41PDgxn2JTEkkrVEvupaC7Pr/oy2XdJBtX272qCzutGfwp+EVL
rJnzYAPRL+XwLKxCpIvW0l5yCDR68KsW3JxBB8DHNJ1wVcy1uALOorAT4ZrKqgy6MybpdK4s
Lre1sTI6zNzfSSKrhN1PMSKklNHBgxO7V+FZMgFX2RO7V+HV5G9m3IywrijuPFF4NVU0Lu7E
7lV4LZUOmjme2L19J5rYwMGhE7tC5d3GIvy70pVYQc8yHiJr1dfeXno2dAR/SXsX6a2S+Jhk
I6m5ZlV/G5m5LEKLd32FZq3tfhphjk3Y5HPzJ0dby2CzTFyzgEzv9we0dAVWPCITco393piL
CXK1hw6+fLnIm6XTil/Ri4o06x3VrCvuDufbNs/PSToRBsb++2/FVPHqXZ5i8xZ5P9OK0FI2
sMn6xO4VduwbIdCL4sTuFXaafJkEfyAHduv9pZYEtSI6sVu/P9FU4RS2A7v380ly6YDd3xO7
pHx3X1ShK6qCnqU7UA0fwtp8wTXY8G5Jcq7RvRnhHJvISKtWXdxJa6h9yJrkDWr9vh9qlo1r
31pK68Ja0emqNQd/1O9tL+mKqnjEJtLinQR1p5Tb69QXO5VdE2s82ENM0qlVey2vLk9r4CGX
X7Um2Pgvn7XndDhC/LhKLRXtWp3NvXtLu1/AjLCmzKAd8Yndq/B8j2roS+/A7j6chVM6XtC9
+q4nKqi72YHdre9UwQyRE7v387WEns4e0CXqblC2u2Iq6FmwAzVuRlVYDEx3j2uWiLtBLWWK
jCubbrVVifUJz9xYkmjc+r3T9Cybkokpd5ZMvWHygRepIb53vKQrpOIRm5Bp1Z+1UkrvvqOA
5ypWTCKQ3rcBzNJxpRqjFZYl+24C9atZ0bo8qEJ+TtNpbNpc1ZnvjzLYQjg7bP4Wdz/Th9CS
cAX7Vg7sXlUnKRP4+U7s7rqd1gdOhHWzUQ2FLTO49p3Y3brOOq7rAru9btdBJ8ITu0A+yEjZ
XUEV9Cyogqz0WqsLLa7gWGZctETa3aeyzrGJEhwXtqzsfxhWfFhWt7tvhZpl4/eGJGfunRWW
divuDefb4L4/nrQfz9hE3Y60NleNlCNqGj2RXRJnPKrbTdKpNWuh5qxq9t8PKu1WNEXK7XDI
5zwdX8KdjRBbE3AQ6V23+8ZWhJZ6Qa0ID+xehaeJBLeCC+zuup3AlbEDu7tyx2gE5wu6vW5n
aGHswG79fCUnA9sCDuhXn8peIRX0LKSCfGVqEoZG/m9Hve6WFO70ls3HJBuXNjVMFaOaoh11
sVzDpt2eY35OsylNXeBJK1VKh+P7lsghHqi7K6LiEZso3PXW2O9NqVa21u2G4m6STdVq1DXG
cM3A/pEddbtJOs1inr+6sONGYL9dDJb8juJOYHH3pIEc+05XdGd9YxO+3MH33IndfVAcgU7o
QXFgtwtOwb2vA7v1/vp3Uhls9TyxW7+/ygk1gzqgewWnhXcGvB0L7BLJORACV34GPczPoBK5
W7m6HkDHeBcZX9878M2RKamYr8cunWP7C3bdlyUub5HFdi8Dptj4Q10iWzliZwq69Y+LVoga
undnoSs84xEbF49aKftbuDNnNEVnlQXfrZ/JxyQdStGPwFp8RyAMhviGCcpXK87Jm9NCQEth
4poVjK4Mnfo7Ks5/lAdfB+0jT+z2mmJBx1AP7G6J19BTxRO7V+LFaCnus8zbfZZ7ChMR1Kol
sFs/n7I/86BF5Qu65Mx4MFt5BWjQswCN0jVmEXN+2b2hGu+rrVrm2ITrSgg8X6eitIgtvKus
WnjQfz/FRuIgpFsXLqIFPJWUJWzGGu/Kz3jEJjSeP2eVnZF2Ag/0V2m828zoj0k6lGI4Knd/
b+fMcFIirzgypjzYTkzenG5SqQgbF9fhaDfg3FvtrfF+AQ8+Q+t3J3a3uIvDFFScBHa7uBPw
+zuxe8Xda/waFHcHdm/9ribfGYPP34HdK+5c4lSwqnJil1Tw7kM06EpqoIchGqVls0KRtQr+
oNYk4B6JX3dr7hSbkrRzdJ4ZR9ELdeLTFS2BtQ/qKlNsJIVrRtYmJWcDreviohUKog42EldQ
wyM2OfrGc2Phri7v4PA6WRFedy+IPqbp9JolhxMQseJ6aIlNog26TyfZmO8fWKJ9xFoFqzp+
1dukZZW8+ylOfDHkA770T+xelWeJFR38OLB7VV5NSmgJ78DuVnmNwRLZid2r8iKeDexUO7F7
VV5LpYHP34ldUsQbtAZeUQ30NEaDMnP1J5AzHJKkC5Ze0tu85Y9JNiVxz2zkYiLnrKhD8ZrB
D7n3W55jI65wWhHjUhsZXMRb412XBzO9V1LDIzb51YpSzGUeW2mwd90SlXdvUPwxTadz7znc
iallhp0F5xyK/0TnPqn8c5pOjRzn7tsjf1Vl8M0WV71l3t8e/NjuxUcFjJF8QfcKO3+BVYEz
cAO7V9hpUvDs7oBuvbfUUq5omP2B3frtSU2iYOPxid29rVAFZfuJXVG8s8Fie0U10LMYDdJI
EjNT7q2iR0xr5nl5IOum2HCSXsJponbXdmBAMS8ZGaXW7+7N5/S9qZl9ofUb47oBttGpS6xa
RvO8V1DDIzaveV6Xp9JaCzdv1Lju6+d5J+m07M+a9CrZiRnsbbJigkV0UCiepBNOjyT+CqA4
pkWz6+aGFN+y7hfw4bNUwG38Ad27vpZUwIaHA7r7aJYzGOB2Yneru6rgWv6C7tV2ricF7Ao8
sXufve7vdtTn7cB+sbbjK6CBn7nmk9ZSK+UmtcDhGYu03f1p2Rwbl2nFOrdSem0G2vjykoZ3
aoOD2dl703yt9fviSovEsH53WjJbQb3ftwDwlc/wiE1M8zoJ32MXf84KWDTY4LE8S6dRK+qq
u0uXQiidFQ0uLO0+PWOWjhVi/9lojdYG0CMjrnpru7+t7bbb8JHgNnyB3V20i14htGgX2O1F
uyoPbPhku7BjeCU/sNvLdmBN9oDuLtpVQcd5DuwSYXffB8VXQAM/Dc9w0VAq114ymqayKDxj
ULSbYxP1N9eoHF6xhUGftzWOxC7s7nPmZ+9NdSXfc1PWphUVdivsKF1K3kmHP560H8/YRPlN
/fZw3BvN4J5yh7CbpBNmxKWJ0/F/PTxluqZmN9B1k2xc0IUZUAs72FrQo9h3zW6FrvtZ2Rng
OcAB3V2zM9RC7sTurtoJuLwc0N3SrhX8RDawu6VdF7DmeWL3fr6cakeT0Q7sV1ftroAGfpid
ocauiLRbE3hadlHVbrDiTrHhaNlnC21XXT9gvVy8pJfLxd1gxZ28N611USuNqFfQtc4vWnG+
3G9rkH88aT+esQmZljvXkiVrq2AT7Q5xN0mnZeuFq2UlZ7RV3N0el39OszFVyhKxddzBwCe/
6Lcclv0SCz7Y33RFx/i3NuEDfXdP7O6Com994IJiYLdrTgVnoU7s1vvrOlzRvOATu/X7q5qK
CXZ/T+zWz1dcq6Czbid2heqk+5RUvrIj+FmuR+m9a6X+iluAffhWFOFGQ7xzbHxzSepfkrK6
HCDQJTEtsUhsA3O0OTactLugoazZaoHzeFd0dfBrNmb8pP14xiY8WkQaafF/gok9cc0SzTmo
XU+RoWg4jX4EYpHCaIvmF/c0fk7fmnB81uLbgmIk8OTNXLbwry46/0kufA3slT6g2zsBCVxh
T+xuhdfQr+/E7lV4msLJHbW5CexehSe+acVu7wHdq+/8jhW8oSKwS/TdoKp4pUfws2SP0kqn
+JukwckeZUmyx23l6mOSTUlioi6GpEgYz4D6bsXeYOizPMeGU43aqDVzLmgyGE+uug88+PgK
j3jE5uWzLLnFCbg8ODH+apvlOTZhsyytEFNh10Voq8Wa0erRTmLy3jT1LXLOopkNTktub4uW
Rfpu79LfoucHq4Mf0N3CTtFexRO7XdihOUsndq+wC7cacETmBd367bWX7wH27Z3YvcJOfQFF
K0MHdoF4kNsFypfbK6SBH+ZnqKvOCMdtgh6w+kUrpJDetqp/TLLx7WUWKq8+dang/HdctOKA
deCVMcfGNRpV34+SqWkFa128qhdwUCK+MhoesQn3PSnNuGsu5HzQAd4VdEbue7N0erde4xyf
uKNnXJTyitNvue3U/Jymoya9kbpSzUXAyc48+SJ4a7tfxX7PH0gFz8dO7F6Rp2FiACdABHav
yKtJCzjreWJ3izzNaNjngd1bvetJCawuntitn0/9DafgwMyJXVK/G/RqXTkN/CwKQCOQt3bz
BZhw+72vzkmbYxO7OXG1yrkVbmAfflljJlhHVZUpNpzay0bQ/9GLENrjuKJ/d2iyzFdMwyM2
h8myVtNcJWZGfxWT5Vk6LoriSSuvXBDYr66vuDs8knmTdIzFukSWXUwZoTJvrrXhLfN+sv2e
gJvGE7tX2kW4OKhMXtC9wk6ToSYjJ9Y/1v8BAAD//+xdUZbtpq6cEQtJSMAE+qN7/vN50rbd
Hy/LpMyl6ZNk5ybn5qPIsjbYFEKq2je7TiYrodfGB3br7yc1+X4Gt3sEdvfBIqN1ny/okuzd
oL/y8mfgZ94Z5Lut5KKt5QpLvK1o7CLju9Kuz8lo/C0np6i1ZMvUQbcJH7Sk7K7e5bu+pufG
ctRrlhDRMbQzywetyEXeigl+r7SPZ9E4QWvSWq+ta8MlTVboG4x7PSajaZG4M2FqJWc4F7lE
oSXXQeHdZDhaxM/uoj0Xxn3r5vQJ3qzuj1Dfsw7mTU7s3u1VUi24unJgd1/OEqpkdGL30ruW
FO2oO7F76V1L1kB56hO7d/3VxA015zuwS/J2A4J3WTPwM9sMKlabE6Kaa4M7RmmFap3xXW7o
czIaTi/1XidEvRij3n9r9JX7wJB0dm4sijas1szykl3DCN6SvN1tz8v3Svt4Fk1ItdTK4qGw
k1bwLLGsm3dQ4jkZTuOmlIlZxf9G6wjbEtuMeq/lPRuOhkMLadUenilod/Jbq2UBw9uuwYfW
4RzQ3Vk7gxs+D+zuvJ2+VLlABb62IlH/LG/XtcAXxoHdnberqMLiid2etzO0h/HAriB2t6p1
vt1e5gz81DiDaqaqUgnNRC4jdoOG2aloIgknhWoLjdgMelStyty1AbGbnBun2y3k8JpPUEez
qrZCCWRknMGXNcOjaCIJ15s0P0aEJhDcMruoyXSQJJ4Mp0Ujbu5CJTQF0XB+PnU3GY6Wwtx7
9a2oF0Z56jt1t4LY/ZIIX0E/+Cd27w5bnFSi1lQHdnfqTtBO+Rd0L7/rCTWOOqC703bVCLyV
PbC703bVwHu/F3TFrSzdS1TIZc4gD40zzLkDda5Bijabot2lHj4nownVmWJVapWwN8UyDzFo
BbcbmKLNzo2T7pCZerVkolLtS0zRhhJ8clkzPIom0m9RLernk2Jk4Ll3gwTfbDiNqnG4opEU
AysAFnG7UdJuNpyQ8M61Vmu+3OBSyLlWuz+d2/FPiPChZgG7bxdBerLgo7KAB/+WMKAwxjJP
7O4LbAV37gO6nwODvOIF3XvC8Q2mgHvRid3665mGYgb2fCd27/P5wQDsuz+gKzKcA6E2uZws
5JkvR4iRVFX/s0tHeeMayZjbSsvPyWj8E8SNNARwwmoEFNH379aCaOpAiHo2GpbsBK4Lmaqg
fdIrztJMg9pEuYwsHkWTU42+4tDUNqUKfrZ91BJRwHYvCjgXDqXo0JLoKZaeQb8hH7Qmwfm3
S+15NLVFMGytv+QgsWjeF9ereN0vaQJWxj75B3T3JaKfy2BNu8Dupnc9g5fsJ3YvwZPUUFXl
E7uXQIXQH+g1cmK3Pl+TlMEi7QO6Is1Z7q+w5XKzkGfeHNqdu5vTY2Oc4K0QEiLVwa47FY0k
Jw+t5FB9Rtm3j1mR5aztvqV4LpiSeoiSkHJvobkC8ru+5Ab7Ni34vdA+nkUTzhwUStzSqOeu
sDXHiiwnD26w58KJTL/TOyWtll9G19uuBzjzvWHhbDRBuVvzT0FluGMy6buheBG/29uYULtv
59gkH9DdxM4qWBJyYncTu1ZxYhfYvcQuzvjgpdiJ3fr71ZwKgTn/E7v3+VoqqCbliV1C7e5F
eOWyjJBnlhG+L2X/ovvJrBGoEsFrDDB0UJ04F01JVDnEb/yfrKDASlnjd9zzfcXYbDSh8qxm
ktUI/Nj5oBXJLhrdYF+eEY+iCc0kabV2cQKhipvQrjH0uG87mQ0nBPqb9uxU1Wke2om7Rsxn
0OI0G05v0U9cufm/FPCMN6t+82Z3f4oqYMYvyE7sXppnyRrq6XFg99K8mrSiNf0Hdi/NC+oB
qtqd2N0XoEVBmnxi9+bv/DepoKLHiV1xRXurBuab7+UcIQ+dI3z39c2qi3RCxcDTEjGc163j
3d47FY2krlTCGKw27qD7VAxaUah4myX6moxGUxZxfte1l8zgYtMlF85O8+5lxuVyjngUTRS1
eSTcS5XOoFhyXiKGM2Z5k9E4w2tmzlipNNQjwUctSeG1v11qD8Oh5KtMjCvnzAzu+5RoanLe
JO83NQE1taywa0Fg9xI7jstCWBQwsHuJnSaDX5ADu3V+oxSRwe7dE7v19xNfU2Dt1AHd/XQd
PVac2BW07lZHzzfbyzdCHnp6+ItbSISsCCizskzs+d5Cay4aTtxZtRhTtJOiJHVFzSv1PNhr
J6ORzNap5pCea3A3zQoiRLelat8r7eNZNE7rSEonj6c7EULbT1astHH7yWQ00fVduUbHhjD4
oZr1r4XD+fofwvHjXe45RAErWAXgo/6V7Sf/FVVA1Ov2xO6ld8UpG+hP+YLuvpxl9D7lxO4l
d+rbANgc+4LuJk8G3g8c0K1PVzgVA5nQiV1xMTuwa5PLK0Ie+nj4W1urf9apowZni+zaXoaf
dxvuVDTO0jLn7C86+T9o47cPWlJ0d5d//JqOxqi3UrirmnWUqK64NB8Ik3yvtI9n0YTECHdR
J6lCD9jDnDDJE243GU41rb07w2tNK5hjyEsKPKNt/u/W2uNwOsVfrYqzbwYFsfJkheeb2/2u
HiB6FDmgeymdpMygnt2J3Z2x89ce9vEI7O6MHRlY9XJi92fswN/vxO59Pku5g5vTiV2Rs6NB
D+PlFiHP3CJKs1ZDAqy0WtCcXVmR5bLbovDPyWgi/Ra+WTlL9v9D6wdXZLmo3uZTv6ajEap+
2uMeQs+gMjIvMq697f39Xmkfz6Jxipb94B93l60bg0stRv00sZsMx09DJLVTE/XpgbNcP560
mw2nveSJmp8hlEC5pdlw3sTuj9AD5Ao2K57YvQxPEymo5nFid6ftBLWQPbG703bhnIT+foHd
zfCq4beegd2dumMDrUZO7AqGZ4Nb2csuQp7ZRWiTUoWNwyEVtuBdoofCg213KhpO1EnVP0Ya
fX9gUt8HLSm2G/TLTkajPUvUumv4taHRrGhl5lwHt7KXWcSjaCIJZ5G9I2FW1EhvWU/F3y61
x+FUteKBRCqyMSyRvKJMdZy6mwyn9ZJbdM1LzgyrArZ/5bWs/IQqIFo6vqJ8Z1mnx2b9PUmt
MHb2O7G7r4qpoJVsB3Y76xTUx+PAbp1faSmDHR4HdOuvVzl19PFO7F7O2VMv6JnswC74lHC5
22ucCVxOFvLMl8OpZo8G4cgngBZlPmiJP/CtGd7nZDQlFd8yWSo7EyC0jNkHrcgq3na+fk1G
I+HdZJ1rbZargVWxacV3jokGHeOXj8WjaJxuZePScw41atwguK4pBRwksKfCoSRaci5NiQlN
Ksagn6ack5Pjy8w0DjfW/XOAMug+9R340ynnf0mEr4FGHgd0d14xdzwvFtjdDK+BZkkHdC+/
66kJaBB8Yrf+euasKBfsu3litz6fRiYdLPY8sSsKAst9mVa5/CzKQ3cOy61Rl6JmBPcTLGnh
HSi1zEUTBzlhIWndOR6sbbKkD6fn+213LhpJ0ot0ydUZa20YJZI1xmuc77OK5XKzeBRNDplW
E+dDpmwCZuR91IqO5Htd4s/JcEKXWEqpOVvX1lBnbV5SD6j3Ksuz0WR/cVpwcJEGVjfGoDfB
W0Pw9gp4tJCDBN/AE7ub2xWwZvGAbmd2YMXsAd1bD5CTgnccB3Rv5q6mImDq5cTu5XWaFPXB
OrFLeN39bXG5HBrKQ/eMXAprZakV1ZrhJcZe9NL5uttsp6IpSbt0jsKz5uwBY0JljVR0kzsm
9DUZjSTuYYiXzTp10G5C1vTw8q3G2/dK+3gWTU6ld6d1qlmJ0MlZVA8ot/KIn9PhdJXe2SKx
ikpX5iUqQEx6byE3G421Yv59iT7rOBahwjnvcsBVxO6XBPiYwa6AE7uX30X7K5hreEH38rua
VNG72QO7l+FRMrQi8MTu5XhOyQuYWzyxe3OL4jwHrA04sUs43v3tbLlcGsozAw0JazQuxp0M
7ytYoUust/mhz8loirOiqtqtUMsVLDora3o+2mjjnYpGQh1Bm9OtWpxPgA1QaYVkAVMbZIkv
k4ZH0YTkSs++ylgkd8KFWpb0Jg+UHmfD6SWHSXDT1kXBQo0Y9aMFjl/T4dSYnBz5yObv0Fuo
ZadQy96t31Iu4PH3Bd1L63yzRIsdTuxeYqf+gQXLxk7s1tllJ2sK7hUnduvvJzWxgYaSJ3bv
+mspFEix3+/ALiF2d+ku324vi4byRDafkrSQzK8qoQ+LFg+t6eUdbLZTwTjhfHUmt/DxJJDX
8Zpoer6bmq/pqanBGApVVkZlQGhyq/0Lr7uXAyqXP8OjaHIq9bj401yMYGe0skbVZJC7mwyn
5bCK7lVCxhv0mfJRK1g32yBPPBmO5ThBSNPKhFbb58lDxJvX/RkCfBX1zzqwezdYP28beHt3
YnffzNKDojvaXXXHnKyDmbETu5fgOSmqDBK8A7v3+Sj6r8HnO7BLCN69Wku5zBnKM8X8ksn5
Xe1aW2e0eGjJ7azxoBRqKhona8o5+8su/kXC1VpWGGf0PMjcTc5NF2dFVDqrVLAzmSZr3f9y
OzvI3F3eDI+iyaELRL13M62m4N6SlwgDjRneZDiNNBpEwvWNQEFOH7QiD3nvgP01HY3V3Fvx
j0CuZPDk2BT9fhO831XhKySwtHJgt6fuOuhMcWJ3p+4UrVg8sbtTdw0VsD+x21N3HVx/J3bv
+qupK6gldmJXMLtbtwnfby9/hvLMO6NkLb4zae6aQXEGH7TEO4MHd7JT0UQaTqN35fx7ZxXh
MHc3OTfOt4uz+bgzb+Bu6+/qGu+Mv11pH8+iiSwclUhzlVDQgWVNfj53NxlOy+JvTGZmNQWl
yfOa2Sk0uJOdDMdyeEb7a+MEXME7u1nHuje1+wN0+MzPJmBV0Yndnbvz1wpWRAns7tydZFB5
58TuZXiSCNUpe0F38zs/4YOCLQd27/NF3RmoUfGCLmF399q35bJoKM/sM5zaKXNtYeAJ0mkf
tIKrKg1uZqeiCcHksCH1N6lpBQ1vQ8x4Cbu710OZnZvuU9MLUbVSwQ+dD1rTLTvo37kMGh5F
Exm4QiUzGTmDAN1AduTtJsNpuZg09u9Opw5aRS9id2R3PS9f0+F4FFoLxS6kBju92b+y4u5H
NPgIvCajFVdk/1gVvpJyA/s8TuzurCK1ChcEBnY75wSlpg7o1tkVTcqgBsqJ3frrVfMVhfZ5
HNitz1dKUgGVvU/sktviO2bjXODyjyjP/CMobopFuXEXsF/UB62IZtjLOxWNHy19zwzTtrjB
AxvVfcyCYOqICExOTZXsC8eqdKcB4JdujaYJ3wrOfC+0j2fROEFRa2JxnV+pF1RaeMXkOOm8
m5zPyXAiF2+1cFbNlOFazRW5+HCa/rul9nhyGktp1nsp+VAM+MG77z+dc/53RPg0+eKFBSkC
u70kUA1OKwZ2N8VroE36Ad1L8QxvRT2xeymeJLjM5sRufT7NSdCX4wVdQfB4IKFx2UeUh2YY
qs7w/Hwm/nVHC+hoiQjfrTDx52Q0JdqSGxMVyWwgJypr2pIbDS6NJ+emV5+TzqRcO6gH4oNW
2IPx7RX490r7eBZNcDUKDV99ifF1OHG1huHdyyzPhUNJCvk3W7tILaAucQxaEs1A73FycjoV
JRJh4UxwzvdtyruK4W1W4cuJDdTxOLHbb4zhdsoDu53agQaHB3RvPYBvAh28kT2xW3+9Rik3
UCL3xO7N3rXEaC/PiV2SvRvUaV0+DeWZh4YqFw51NOcR4Nu0xEuL7Fa67nMymOIUPyRAtNVC
BTz2lSUNllQHtm2zU9PMnDyE07CwoeLXbUUFHd82rnwvtI9n0eSk0ZmsQR44v0raMJGWFWyI
bnUFPyfDochlUG4elJ+4cEniFdm7YT3g5ORYJjX/SPVcfbGh5Y3vesBl3O5XhPii+KeBQnwH
di/F01QZJAEndi/Fq0kzKMd7YveSvKDl4LfpxO7N3/VEsNzygd2bv5PUwdfjgC7gEaz392Z6
GTXoMxMN7t3ZkDYneDWj9q9LpOtGNmlz0ZQQeystn3+iJhorVs7QJm0uGvGTi4Q0WtRsErjW
YtAPlwXq5dPwKJpXWWAI+nYPpSlY+rOoLHDE8WbDCRE+qU08lJYrqj/T1zDw+1zxbDhm3I1r
70wdFXqYza6+Sd4vC/F1NDtxYPcSO07+fQCJ3YHdS+w0LNPBQ92B3Tq/TIkKaptwYLf+flJD
9BPu5w3s7oNF66iU4YFdkb27LVz3DffyatAnAvrhyWm+OZXuS5BgpZYl/mg28Eebi4bDK8dZ
NPfauIEZIl7Tv9LzXWb1a3puzIhLqyJUG6hLSYvuMgcOuHpZNTyKxkmattpqbsXCjw+9ml1R
9Dvs+JgNp4W3SSNTI0WTq6ukWgZ3s7PheBhNWusWCoOwycmb2S1gdr/UztsreL46sXs3WEnW
wOPsid19OUtgeckB3UvvQqQCVIA4sXvpXUtgK/QLuXflNac3oC/0iV1SdXdfC6WXRYM+kc0P
lWXR0orvt9rB3EMMWkLt7pt556J5ySyz/4fNuME9IotUlu/tSGenpip1LT477OwBreuqK0y4
+LYz+XuhfTyLJjRXnDWYVHGWah1WWV6Rg7xvRPicDqcxa9WacwsFUDTLtYbZtfsWntlwLIvT
bc5GFVaPfd/M/jNF+LKB7agndnfSTjsq0XJgdyftLD/wz8j7/TMaat56Yncn7Rrc7XFg964/
J+Jopc2JXVJyd18JpZdJgz4zaSiZ/OW14psuej2/TF55kLSbiibyb1zJaVCX0uAOhCVJuzrQ
vJ2dG6shWUcSVvNoPnVO8fb/UyEd5Owuh4ZHwQSzK1XC2STqd+F2ikUafANmNxlO8x+p+BsT
7K42tP93kbzyfcfsbDhq1opyKY0KwR2z+pZXXsDsfiVpVxM1kKCc2L0bbElZwX7FE7s7aScE
duyd2N1pu4qq0L6gu5N2OL1rv0DvesqtgceLA7uE3g0Sd5dDgz5zaPDzerThUjYh0OVpmT/a
HVn9nIwm1A5b4Vz8OJdFYfeMFWnITgN6Nzk3zoV85fToRBDwniwGrahPa4PCzsug4VE0kYMj
a9SyFW4Gq/j+fOZuMpzGzrN6jblBayEX0TvWv11qj6MxMiWiSiU8idG0qv0rBVH4Hy/C94in
gBRlwTdyARn+NWlAsCbmxO6+v1ZUPO7EbqfCYEWRLREUeDC3/s1LxOi7eYK3/nrWEmVQN+bE
7p3dTClKzrFf8AQv+JgwDwoUL1MLfWI0YK9zhOWupRKqQGdLhHVJR7nOqWhKetGtVl6SK2B9
qw9aoR1T7d5KbnZumI44ip9UwBK4GLSCDN/a/H2vtI9n0XDKWrTlSEIr6GwTY1YEQ4NT11Qw
lFg7O3MsrbSKFqKnFfkiznVQCTsZTau1+PmxiLKAN5zhQvVvZML/HWnAkqyDPR4ndi/F05eB
NdoDYNtJgKWuoJvsid1L87gmK6CA8QXeTfOygArVJ3br8/WSuoGuhid2ScZzsPVe3hb6xG+g
JuXqey73bMxg3aoPWuGiojJoMJ6Kxk+bxLl1our7Fbh8yhJlD2qjzoCpaOLDlVkrRQ8YWHip
k9VjfylVvBcr0svY4lEwnESkZfaQtAtaXu6DfprkTUXjfK1Ia0bRV15RqbC0wtSc6VbO+ms6
mirGVTK1qDlA7QvnNq03yfttdcDaE6M2Rid2O7szMEV2YnezO7CA5YXczOwsZdQO+gJv/fUq
p04gNz6xe5ldD1MM7PlO7Ir03UjQ4zKQ0Ceq/jUV6+Ee4Q9YS8MuGOuSAjKygePCXDQlidPT
2G79MFdBv78YtCJ9Vwf1Y1PRqH8WWg9eEn7OYDQ6mVX5C33425X28SwaStp6NExHRSwTWnmp
awzlBu1OU9GE6nFvWriGiXctsFbyirvse6b6NT05rERcjFvLsCWVD3pzu0Xc7lfUAUN8E0zg
ndi9FM9SlNCj/QCB3Uvxqn+eCGRRB3YvzSviOzWawDvBe2meJKmgKPGJ3XxPK4kbmMG7wCtS
eLfVSr79Xj4S+kTcvyVS812dKJdewe23LfL4GN3TTkUTV66U2apSzQ3UiF91TzsielPRBNEj
8Y1XRCtnNIe3RAc63za0fq+0j2fRRDVlKCH5IlPJGdRgWFOCOSR6U9EE0cvdOpeivaEG8bOm
GH+5qR10tk9ODjf2deYHvtYFLbVPc+U7b6L3uwqB3DvcbBzYveQusjZoAd6B3bv1azJGyd2B
3Tu/mhj8Gh3Qrb+eWJIHxnKyuxeltHCSAL15D+yK/N2thYRvtpeFhD60kOhVTXxvMhWC7cHW
tBoPRNsmoxH/iarUXktjVONnTf6u3UbzNRmNpFAHzEJarBjYOB2DVqSIbrWSv1fax7NoQvW4
moSjXhxP4HaHJU50Q33AyXBqK1lqJv+roW1peRFN1QGvmwqHojhSMrdSemmoY8FkdeSb1/0R
+oChCInSu8DupXfFdybQieAF3X05ywVMG5zYvaWVnPy8iX2TTuxuehdmTyi9C+xeemepo+T4
BV1B7sr9lmuXd4Q9845gdnpHpZSqChaJ+6AVZXc22HHnomF/jXrhItKzVVB6hSfvmP5/zm7g
3TYbjX+znN0xhc4w2CkSg5bU3d0XeNrlHPEommjRig4Rad20gNuKD1pRdzfidnPRvLidmb86
Vaug29AibnfPvL+mJyfnZn4oalFxCatRztWrvrnd7woE9oaTusDuJXWSMlj0dEB3Z+wUFQY+
sbtnF625O6B7KV1NFRQhPqBbn05DtAz08zixP5yvs8szwp45YHQTot4tKtRAk4UYtCRfd38N
OxtN4ZDR09yFULNpH7SCoPZbB4yvyWjkdc7LGplURb1WZFG5/iBfZ5djxKNoIvNGr67sIrVV
kDZsyNfNhtNyyeIHIWlNCqHhrGg0H+br5sKh2B1LIe3M1VA9ER/05nT/O6f7JWlAQZ1uT+xe
aqeJCnhdfGJ3Z+xEUO3nA7s3Y2dJwUK2A7qX3PUUvp3YjnZgd9M7P9jC9C6wCygE9fsqO7uM
I+yJmL+kYqFqp7FRge0/ssRCi2wg1zYXzJFXjutlCr1D7Gzgg1Yk7Drd38bOTg2RdGsS7hGC
0YcYs6TG7l51xy7TiEfBUApz5JabhBAlKIYSg5Zwu7tD0edkNP5ChyB3YarKLCDzjlE/ze0m
J8e5XXWWqlatg6KN/1ZuJz+hCwhe7Sy51lnW4rFdf49QB+gTu/t+mMxAvnlgt/PNAus8vrBb
57fVFHdPWBn/gd36+1WnNaDB6wHd+3Q1FB3BxzuwCz4lMjCAsMvNwp5YDKgfFKMFIlpeG9i2
p0vkMsjoXpdlLpiSSmeRpiGo20Dt5hi04oK4DrKJk9E4CVCutZFHBLLnssZDbtS9a5eXxaNo
KFlWD0V9nZUMVsv5oCX0We5kZj6nowndn1Ja9zmqcPZNVsxNHgizzEZThLRbrp2agPZ+NJmF
/9P55n9Jfa+A/sAHdHs6kVH9pgO7m961B/Ism/VZuqZaGVQXObB76ZOfVhv4fCd26/O1hisr
ntglBYCD2+LLzcKeWAxoskpiTXMTzhnldyvcykhvbyQ/J6MpiXPnXv2PEi0eICNaIUdM1e6b
dmfnhq22LNF7IwxG44NWNO3ei7t9r7SPZ9GEeXHPvbMTPLiPyAct0SPWAb+bjEayBmG1nAuu
rixLhK9vuffXdDQm4u9MNQuvP7T+z978bhG/2y6852Qe1Fg9sLupXcngXeKJ3U7tHtwUt903
xb2mxqgo8IHdS+5akgJS9xO7l9z1cHbGuN0LuoLa2YDaXd4M9kQyX1Mjshb+oM5NwOUQgxZE
U/qgEHAqmpJMi4YbXs/hzgBSO1vS2zGidpNzIyzE3FtVMViPZUUbMuc2qEm4zBkeRUPJIwk/
6lKkEygjSEu6iAZljZ+T0USB4ivdpVxyzmDF0qKyxvvGm6/pySFW603D+FhAv6zZxps3t/tT
hPc4EaF72IHdS/HMj+ogBT2xeyleeAuA5WInduv8UtYUtdegbNwB3kvywuYJNXI4sHtnOOeQ
JAWn+AQvyeHdWxrY5c9gz/wZeq9Vcu2V/d9Qg7S8xCCtD0q1pqIpzvdVSq7MziIbRo3Kkpsz
qnpHW7+m56aSNjFlo4ZWOPqgJUTvVtvte6V9PIsmZNrCBaR3LkoGi/j+tPDeXDShldyodYqW
ZGd6aFFgX9KTfMvCv+Ynx9mjRGOa+hcf9gL5V5oF/9uF97KB1p4ndi+5Cx1d7MN9QPdu/JoM
vX54QbfOrWhS8Lc7oFt/O6mpCFhTeWL3Pl9LrRgoY3JgV1A6HRRDXcYM9kQtnxPX1nJ4GfjJ
DKT5vGSjJeO7nelzOppw/2jSeigQG/hlSGUFQW1lkLubjCb6Iixyqj0aLNFo1nRGDPo8Ll+G
R9HkqO0Qa07qLHtAsErdEmnoURPvZDiN2HrhTkq+6LBPQV6S9R70rXzNh1OEfVZMoga3YNvW
bN/Km9T9Gap7Cp7hT+xebudHbVDE44Duvpklg4vuaEUZ0xNu1/3siGraHdjd7E4zmPQ8sVuf
r5REqD7+iV3AIGjE7i43Bnsike9kwD/m3bfdStHAhzKINZZogzTKZDTCmXILATEpFVXdW2OJ
ZoNS98loKjeqxeelUUZPsamu0akb1ABcZgyPoolG9lqtamNlQp2OfNSSqrsRu5sNJ6splV5y
CEVjKZBl7O7uzfmaDqeXGkJA8qryZFjw+q2p/L+zu826e5oMla86sbtTdiqoxuiB3Z20UxXw
su7A7qV25nMG0vYTu5vaRQIGFt9rm29jne6+NCwwZuzQBeRBdJBMufwY7KG7hIZqRmX2bbej
5GGFqaATu0HJ3WQ0hbvvsiXaMQkWIF6ivVdtcD02GU0o7vmG24uVDOsi6hrq8Lcr7eNZNMGE
xDl3iCOyLzeY2C0Rqxvps8yG42xOmznJ0kJgBt9H/Szt/poPR9UDkhIXsgKq58zS7jex+yPE
9wqBRckv6O6knYHO6wd0d9KOO1qIdWD3zi0lf5FBYcUDu/vSs2TQZPnE7k3bhb0J2O5xYpew
u/u0Xb0MGeozQwaVqrX5qMyqMINYEY3xvRbKbDS+LxXqftKszUB7+UVcdZS2m43GTyyR63JK
5LMEFhYv0ncbpO3q5cfwKJocdr2tZc7mrAgt9cmL/HoHabvpcHLvfh6yQsUEvKBZlLYbuWXM
htOrStcwuZbWwab52QaRP53d/Yj8HmrbusSy9R8rwCepo/67J3Z3TpEZ9d89sLt5p6A9Mid2
6/w2SRnMIR3Qrb9etVTQLtkTu/X5LNoiQK+WE7uEdd5dEjkXuDwj6hMdf/WZLSGcIWJGoF10
DFoQzaiNdy6aOF3WVp3ONraKetUkW6LAF6Jyd0xgMppcTCmHPFK0ioLRzHmi/n+adnsi+F5p
H8+ioRTOF41CUrgX2AVsxflmoFn3OR1NeF+UTNRyLbhm3c+2WH9NR8PxVybziREwl/Nu7vjn
K/BpBsvtT+z2YkADbz1P7G6G1wxUkTuxexletEhg7/IB3cvwSiJBJYwP7N7naykzWBNwYpcw
vDtO5Pvu5RtRn6j5a6JWutXqu28t6OueVshtD/t356Lx17ybZGpCcXuMcqIlzR4933t6zEZj
XLPGf7loBRtxyqQyGqzz9r3SPp5FExrLJZfCLTsHz6gJr625NL7X4JuNRixnDZPkltEbfVqS
wR5qLM9G49/3UoofRIUJNkh+ayyvYnjbNfhKBanTid1N7RQ1uD+x26mdPtDg080afC3aS1AB
ngO79fdrx4kSe74Du5fcSZKMfdIP6E9Tu8uioT5zzyBirUbZ/+c8AqV2KzT4nITdb7hT0ZQU
fq9WIhWZM9gF5oNW0O5WBymVyWjEWbcqFws3rZ1CM5zbgNpdFg2PogkN9JIbeTwqDdQyiUFL
yNAgTTwbDftSy9EzXhtYahGDlkRz3+cxF00IzUQjPzVVIgE1jWLUm9st4na/osEXKopgXduJ
3UvxXr4O4P3sgd1L8UJXD60LPLBb57dbqgQapJzYvRQvJz+mYs93Yvc+n6SCakCe2AVE4l5h
1bfey6ehPvNpULKayTRMZUHO74NW0KKRR9pcNH6Ws9h4/UCnrTWU5OmK5uSRR9psNNXpN2fr
PXtEqCPIGteJgSlvvXwaHkUT/rrsZDVXNkL7RReZ8o6ElueiiYo4CwWd2iUXAxN4PmqNks69
1OPs5GRuuYQ/WvjpwKa87wTe/97zsV1/r4C5iQO6l9ZxKtZBWndg99K6ENUDW6FP7NbZlRLZ
Qqyb4gXd+utJTQ1tljmxe5+vJHamhv58gV1B6m4t1n2rvRwa6hPZfE5+Ym/ViUM08YGtXbzE
04CMB/mUyWgKW2S7WpbCoEPDqlZeGpTdTUbjNKhSjXK1imqM8xoa5Dzo71bax7NoslNUckZH
3Lp6VGh2aImP77DZYzKc5ichq60X8bkHW3Hykiyx8/wBq5udHfFY/JX0Ix5aAOCD3gJ8C1jd
LwnwNQalKE7sXnonyeCs3YHdfTGL5kAO6F5yZ/5qogLBB3YvfWqJURmZF3Tv0/UkoDP7AV1y
KXtHH3zDvTwZ6hOhfGdpFgVD3Q/p3EEXA17iq0omd9F8TkcjxoWLdM6aQYW3RX28ne7FlWej
KRKaGSWuMQ2U711DVIcqLfWyZHgUjfOAFu6w0jK1XsFTRIz6aWo3GU4jZ0POVbtluHVuFbUb
qLRMh1OcePubo34o6qBy5Vtc+Z8ov+dMg0Ft8xO7O2enaNLpxO7O2amC1YAndi+to9Q7KDFy
YnfTOt/VQPm9A7s7a1fAM8UBXULsBrIZlzNDfebMkNU6NxHfp7SjWa4lGUgbaKLNRlNKq1qY
cmmKU6ElRmg0yKNMRsPklCGcVVkNbC6NQSuuLm/lZr5X2sezaHKyKOmKbh2TjDZJ5SV9zJxv
+0I+p8Np7FSIhWojQVt/l+XsBpf+k+HUUmpvvo371KA98++k3T9afi+Dq/aA7mV3oROAalId
2O0puwYKyZzYveyuJlQ/7oDu5naVsLPjAd36dIVSeDOg4oWBXXIfO5BBuXwZ6kOXiUyUsz+f
wKpHMWjJfewgaTcbTbUw6tRStYEpVR+0Ym7abe/B13Q0ymKx20ovqqPF9n8AAAD//+xdzY40
uY18ohUoUpTEF2hgu59i4dMe1j7svj+WrEo1YA8yv0iNWv31uGx47EOk0VH5oxBFRvyTMeKa
stBF0W6kMtxi4zrAqkamiRAVU9TebZG18oW2m6TjOqiJ5OqPWqRm/DZFu1k6TfwZay5Y/eUB
l4VZa8Tv1Xb30szjX9gS/sQu+JT8ab34P//4+z/+7x9//++//Yf/Uf/xX//7t70N6Fjr+WYt
Bsqw3+H2fY/voUVXoIEnXQO8V/BT9eUAbCIY4L2PWbEEz9U9sVvvMReKEBd0z/QE7xXWFosK
2ihygPduTFSTS0zwvP4AL/is5KsWuZHd0e7kKYQFiXLVrNa1gg45ftGKMerSLpoxp9hI4qZN
siqxMiiXZU24cz+Vyx+TbGIroy4uzZxOB8/Y1mxlorb3qyft7R4bShyGPzlbbr6pQQ/sV5hL
MNPFNnOSjUql5rtx39C0AjtVr7F0LBd9v5N0xPfKj7Hw7LtmRunIVLnvVdf9TVwQLfdwSEP1
3hO8V+9lSdrAqYwB3nyAX1IF+x4P7Ga9Z8kaeI42wJv1XkvU0AjHA7xX79UePwvY2/rALjnG
P/N1+0/tI8uj38lXCOFWuXQRpWa4S90KNqWeH+PPsZE4+LbSupQqDBqSy5KDbxcx51Ymc2xC
uIUC9w2rZQb9u3lyBf6D2jsv9faR5HGLjQu3Fr1e+THdkeHpjhWtwCwXHSOzdLRkqb7PdEHO
ndGGxiUJRXbqJPoxTccVay/+7qh2/wdKZ85K9CX3vtsSMbuuTxUNb/pEb1Z6LRk6QDLAm5We
+uIBzn8P8F6tpzWJgh/bAd76GyprKqC/3YHdq/RaTBqDanmAl2i98zHrPhI0+r1cg6jqxWvM
RRXOnKgrmhzrhSPxHBsJdSSVqpBKz1h9Qpaoo9z62b35mGQTsq2Thd1Mhd2ieYmTt2u9c4PE
PhI0brFx1SY12oNrtepfFDQxeUUkAPOpMfn7NJ3i0ij7HjNHHgiYIhBXLSntnZtxztKJnGRi
169OBvVbiKteWm+R1vuO0p6LuPAoAetSB3iv4OOSfOMOTuY8sJv7BbIvOnDz5hO8V+617F8d
MIVlgPfKvcIpo0/hAO8VfEaJCtjIPsAr+jjLRcllBGr0mxEUnXP0PVpVQ7td0hLrx9LOD9jm
2Lh2U9PIB2ku+8AnSFYNX5/P6Myxce2WXelZzsQRaYcKvhWdgnxaqvx80t7usQnpZlqMpGbX
SbjgW+GrwxduibN0inXfXuSYbutobBQlXRKscxoE+TFNR2KK1ZQla85gPh9NvjovwfeNdola
eqqo0e8A7xVRZql3sJ4ywJv79TjB2WADvFfKV0sVje1+YvcK+SKJGpirNMCbtxq++BDY0T7A
S/r1LmotI1qj34tviCkTV3m5+/u81ac4l1PX5fdpNo24M7kYFpKC1ijbioW3ndYoP6bZ+A6m
KiuVOF7fm/JL5wE7fURr3GLjgoDM1XdrriK6S1dURqyYK3fJ/6tH7TadUsQ/PFSrVlG4w21F
ssD1Ce4sHcoPP+wIp0Gn9l4nuD/XPVHV714F17AB3rvKUo0iHagDDvBmrdfiMwBKvQd2r9Jr
LeWCejwe4M1az8JUFw2mfoI3a72WpKFP4QFecYJ7umT5CjwSNvq92AOmXHKMYlLujEZ18Qp1
dKn1JtlUk941wo4I7ejNS3xdrrXeJJuwD4pgbimuj1Advkjrnc9m9BGwcYuNqzbOrlhJ1O+8
gf0ZcdUKOno+mD1Lp2iYKRYupfizhsafrDB4cjrnwxnTdLKQb/mkSq4VHp0pU0r8pfW+0U0x
dJtlsPl3gDeLvAjWAeOBB3h7QY8Lev51gLcX9BSMuTmwm0UeJ2uoE8wB3l7Qowbbej7BS0Te
xdI7Ejf6nRSEqM3lqlp93WgC5ocsKujV06LR+zSbRp2jd6p1RbeCftGKkYxLkTfJRkvLxlaK
xSQDKvKWyIirgt7I27jFJgp60W4oVJ0RgzdnUUGPTgPA36fplBL+nQ8yuYItoWsKepyvTm1n
745ZCTehHGbzghpFvgp6K0Te9xT0ij+MYMrtAG/WepY6g703A7xZ6/XUCzqScYD3ar0efS/o
5M0B3nuXlf3GoYM3B3jvXyixCmFDagd2ida76NAbERz9TixCThxGi6X6Bz5CONCC3hKzlauC
3iSbal2FpVRiA6sSOw5vJ9m41vPFtyj1hjZNrdJ65ULrjQCOW2yiNKdOxrWRWgfrCX7RirCX
bBcNepNsiqqZZXO5ZxUuT67wqriu583SyVooF99NUhGwsE+T3aC/u9QTWOrdWDHAQI0VWRo/
2esvK9j3NsB7l/3cEppdfmA3i09LtYKjAwO89R7zIwcYnQc+wFt/w9J9DSUwl2+At/6FErsG
Ad0IB3iF/DyVOC4KRlBIvxPe4D9e1VwtskKIMDnt16zQ0q6tzjXBFJnwcXG9JpxdTBNYN/WL
Vtwau8hdnmPDLr38rphS4Y7GJi5Ra3w66/L5mL3d4xJbWLXKZEW0wtMUS4z+zuvz79NslP2z
3VrV2B3AYm2FqyvTqd/nxzSdmJ5vIaMrWwXP8WjSVPJ3157/RkZ/LTUGwyoGeHONR5IxalN3
gPfKPS2+GIJvzABvlns9VdhC5wBvlns1aSlgaMoB3iv3wq25gMMsA7xAU+R8IfdGdki/k+cQ
FS1xsZdD7zXYAGaJZdml2d8UG0kxZNx6jm5IEzAVyDetK/Qenee6zLGJ+BxupYtGUA2oxddk
7rjiO4/97iM55BabEG9EvqeI6GIRuN9ukeS7KGxP0lGhXHNX32HEKP1WyXfh7TxLR3rrvm8O
l0yq4FzSy9v5R5v9NXhgdKA3qz1OHY09HuDNak8To8HHA7xX7RUXHw0sFjyxW39BzTlyL7D2
hid2r9Kr5JoCFHpP7AqdVy9GgkdMRL8X4aFdeqVipFnAw7G4aIXOu4jwmGMj/iJVMe0uq58/
Fub7suRUmS903hQbl2yuHhv1OIRt4Kkyr5mr4HyeAt5HSsQtNq7YuFql3Pxb1wpoiB72gCuO
lfuFp+QkHacgLqashkUmuG+Oq5b0d17ovEk6IvzIAO+tKhXU1HmujPzSeb+P0V9PDT1C+0Tv
lXuPYzFQ7T2xe8VeuPcR6gFzgPeKvej/BGs4B3az2AtDblDrBXSz1LPIikC13hO8ROyduzrb
SImwewke2lrptRKRMhg5u0rsXRT15tjEIS4ZudxTbeCGdVmAx7klxxwZTtxdSxTfqbYI1QO1
Hq8J8DivHtuIiLjFJlSbNNZWzPUEwRZ/S2pgen6KO8smUi7E90nGlTrouL3K0/nUovpjmo6I
ZSFRa/4P+BD3Zen852dFvsHhT8CVa4A3d+nl1ED1eWA3d+lxqgxarg7wXgVfa2qG9hEe4M3l
WvMvDvidGeBv6BUFnTAHeInCOzfXtZENYfdyO1w1lppdwVM1sHfTL1rRplf6xcI7ySbObH23
VEtvGawYLTKltlNR9DHNRlmtKlVtMRGMqu8l9a92IfFGMsQtNjEQXCizi7xo1ANPY2jNKTTx
eeV4lk6R6h+fyOSN7Dm4nLcmkvfszfmYvztWa+++mxBuaCDgayD4Jzv85YRO2x7YvWss92QE
btMHeLPWa/516qj1yxO8V+u1UMBgMv0Ab67VusDsYEfSE7v5KZTkwgjUogf4q5XeCIWwe4Ed
LubJStfsqztoYLFM6V0sv5NsalMhV0WVNKMelmuUXuOLYt4kG81FXBy5BHeph6pwXeGVwvmi
ajwiIW6xiZH4rL25nFBtBJ90rrF+OaXzPk2nlFaVyd+ecLTZaO+XzS42FbNsqESuod8eM7ya
9xJ6C4Tefnu/YuCpzQBvrqNw6nA174HdXs3LveDmfgHeXs2D41af2O21vNzBZ3CAt9fy1EAF
McArFF4+N3yxkQhhN9M6mj+ErZdOjG7tdtTyJtnUHvFbvZpVKaheXaPwynlr3iwbV6sialkL
M9houKiW57/ir560t3tsoirHWsW33S3SnuEjwSW1PD3bGr1P0ylSSu/GcWhbwbsTVy2p5Z3n
PU/fHVOuJVMW9TX9pfA2Krzv8vbjiomAA7tZBGjyXTpYyjvAm4VeT2jayYHdXMgr/rVBj4AO
8Pamy4Ym2w7w5lKe4k2NT+xXy7wRBmH3wiDCiqQ2Vt/JMzj+uErmtYumvEk2zsRUpLUqoH1H
XPPVdbxJMpqrVNHKZox2+KYVZuGRqPGrB+3tHpuoyJXm+kTFH7gO9hjuqONN0nGN15o0IylS
QZPURTkd5TSb8WOeDtVWezZpXdDZpb9qTseX+PpldKp1xcHjT3b2Aw/wntDNiz650gAtmwd4
s/Q0fydBcTzAW+9w+N8IwePTT/DW37B0SdbA9XaAt/6FUloCh2Wf0AUflCtPPxsRFXYzoqL6
I2hxukeEZ86uOBG/MvWbYyMp+rfi0NXEuqImLyv6dXPvF9pzik3M8bZSiTplbqgL59fb+tkI
qLjFJmz9imu1Up2U6zXUhHnFVL9v/i4qjJN0lHuJERerrTW4Jvflvn6zdFxFV5PKJcqM+M7g
5eu3SuN9j69fT6gn5YHdXIOiRBks4w3wXrGnxT/TN1z9ArxZ7NXUMjhcO8CbxV6PLAjsLxzg
vWJPJVoVsL9wgFcIvqta48ipsJs5FRI97rWrwulBa44trweAp9hItEA28eVdrXUwEUXWVE77
aeX0Y5JNDPMKmebsMolB66NVE8B8nkxoI6biFptHFFErqqRUawctF1e5+p3SeZ+mo/5/StW1
eFYpYPvCGsGXzc7dXmbpSFeh3oTYyMAPwcvV7we7+qmv7KhQGejtp8pcwOa8Ad6u9jqhw8AH
eK/aK5IaeCT6gG79/TRT6mDU14HdrPNaogo2Nw7wijPlK6OXkQhhN8M6WumlSi/d9/Nb0zqu
XP3m2ISrn0XOsbiwzhUt7K1x9SsX9htTbMKIufrtIe3cBU0oWnMK+7DIv37S3u6xCVe/okVa
tdqrgB8fWhKlcunqN0untIdi1az+rIGxkatc/eSidXCSjnDvLsNdunLsLV6ufrt13je5+tXU
Mxg79YneK/eUUyW0T/8A75V7NfsmFm3SO8B75Z5mf1VBf58B3iz5esTCgTNLB3iv6KsaRTGw
eHSAv/o0d8RC2M3IDg3Dh8qqtYOma4tOcy+Le1Ns5GGjaNZJNFrwdtr7Nboo7k2x4cS1du0u
9V1UwLW9FaqCT32pPx+0t3tkwqgvnIKVS/PbA4ukJfZ+fHpv3qfp+DvjmyWuqqUL2Hi/w95v
ko5/oPxD3zKXzo+0wZe/3ybN9w3+fgVVKAO8V+VlTk1AT5UB3tyv59ISPgo7wHvVfK3+6QRr
OE/s5sKtRf8IesT8BG9+ClsiQy3ED/CSA9yLpXdEQti9uI4og1lR0mJ4LNvXzwRPsgl/P2dC
nbuBnmuLZoL76XzFxzQb5WxMHE5yFQziXTQt8rAovX7S3u6xieleycSVm5FxR1vcvt7fb5KO
35VSH6HCGnpvr7/fL5+1+3fHtMdUkm+QrOJ1ytdQ8AKR923+fgxOOQ3wZh2QE8Fmzgd4s9Zr
vs0B/dsHeK/Wa5Q6+hsO8OamzJ7iSAEeDA7w3r+Qo3KCujkf4CXHuKfRqJWOUIj4H7fUnlor
rvdIW0d9H10iLjnGPT1bm2ZTu2VTiX8yGGfmF60Y226nguJjmo2S3xKrZCaoI9Iqj79TNp9P
2ts9NqHbzHxfwcWKKeyKt+RU+tGefP2o3aZTNGuO8RnfYTSCh2m/2ORvng4Jx7bPWDvh5tQv
tffn1d5uk78cdinY8jrAm4spkjqDRccB3l7SywU1kT3A20t6xOAY8wBvL+pxAQNuB3h/Ua8z
bvQX4CUy77TUUikPKXE3tKNT86XKNIOEvr6mN02mhn0FtUy+e4JdC786s2OajXLjQq4jqrUK
1/TW+Pxd7Cfy0BF3MzvyIyG5FOOS0ZPOr/b5m6ZTpPijpr1zR/t2v97mb/7mmN+Y3EVV2eCU
uddMxgqR910+f75NQQ2dn+DNKuBRA0Ptfp/gzVqvp1pBT/oB3lzSizlFtEBwgDe3YlJqoPvH
gd1c0CuporveAf7a49tKPOTE3dCO0lrXUnIBe+V31PMmydQwcy7USxNwp7CsnHfaoDdNRjO5
/hZWqbXAVjhfHNkx2LzdYxOFuTj/0eJKQgnUravKeadeOO/TdJwHd80Pb8naUfeYry/nzdIh
pVKpaqmFQJfMv6rVH3+F1R86xLd7ogAs+Cx4bBeo4u+xH/TlO4OVsQHeq0aoJjgB44ndrIgt
dfDE48BuvcNCLnENtOIc4K2/YDGO9hrMkOaJ3fr3iVrMGoG/4AFeUfk8VV2uU2SorjvRBpwo
jrWkFG0uvMAtSFoS2HIxpzzJRhK7IFbKVrT3jrGRJQ4uufWLetTkvRHruWYNryA4UGfyzPEP
UxEXpU8ZmutmiIb41059v8KWUbOg2UnYf/WjkYsq+yQdjWgT146ZuCm4eferlrQzngbQfMzf
HfPtSs9s4XYJDsW/ap8/3oCwJd/LY5+WAd5+2K0dnW04wHvlnpYYmgHLiwd4r+DjqAuj9nkH
eOtvqETJ1zlsTRjgvZKv1SRgNsiBXSL4LgpTZYiKOykHnLI/g90Xr5xzQXs004oGkivH6Uk2
4TjN3C3nTnF+jwq+JaZw5wkU0/emSDaRwlRKZ6wqxUuOU7PZRUdjGZLiZtqJVqMuwUkNXGT8
qhUGhNTOpnrfp+loUeHamboyuPfzi1b4Z9NVtX2STXHdatXCuN/3+Kj/4F+zAvpv4T8oYR8N
TtkO9PZ+st7AJvsB3iz1FJfLA7xZ6lkqBp4FDvBeqef6sjVwfGWAN0u95t968Cd8YldIvdNT
Ll+AdciJewEW2V/hLDEkwehEwSKpV0/Ndd4n2fgHiZxP5HOVjnrSy5JqmEu9i9re5L0pImRU
qkhFW83WSD3/cv7ySXu7xyYaFIvfnFZza4za6yxqa5R6psPfp+mU3vy98YdYqWiDZ3tXOIFT
uTjtnr07pcfEdSuRfoDX9qak60vr/T4ehC1RAQvtn+jtjWVFOjop+gRv7hjIvulBk0cP8F7J
pzV1MM/pwO4VfKX6pwQ8vhrgvYLPehIGNx4DvKK9kS8W4jpkxc0Ii0yNXCNxVJFgm7sVnn2X
km+KjSTxdYtzJJYxgSN5MhmK9a/HuXI2LPExfW9KxMs2i1iOgo7vfbWx8eeT9naPzcPYmFvO
lLWogpXxVce5pxNg79N0/KNTKZS+qv9POF5kyfbCTi0I5+9OrUVIOimbKCzIpx62l+T7ZgtC
M1BCDfBeCWWWDHVxfmI39+txqq3h08oB3ivlu6XOqD3bAd4r5CPMhNFj+gO8eauRw1AN3Wo8
wSvqelfVljaExL1sEREqj4b8ntGlKi9ZeWPW83zlnWTjepW1KftPJWC2iF+0QrLaVR/VJBvX
QtRj8rrZY0gGm2JZcUqY22mG3GDzdo9NVI60uZDg8NlRMKl0tnL0h3HliyPcSTqliGk041bc
YWeFAeH1DMssmbCHjAFs8+0ReKDysqT54QaEBRx8GOC9ayzVyOXGRzMCvFnrtaghwv6DZYUG
uBMoQjmZoL3eB3jvPVZKVsDQrCd2s86zVCqYETjAS4p5F640fWiJe3EiUk1NYsMmAiae5sk9
/B9saS4W30k2jTiGTShrY9D5JC5awKbbmTL6mGajWmOgoRXzpxy1UlwS9XJeLvp80t7usXmU
i8R3KhRpzhkcDZstF/3BfPBiNmOSTlEXqzn6BWIwHlZ6KzoPS74oHM/SyZWrS/FIDUc/BH7V
1MLwUnrfbD4IN5cO8GaJF7bRBC6vB3h7OU/IwBPbA7y3nGcPGxKwIPrAbi/m1Qaetw3w9mIe
GViyHeAVIu+018iXXhtC4l5mhfguzar2ltXQfPDJrKg7xbxJNi0zR/6duW4FaxKLinmXIm+S
jT6S73LjboT2gCxq+T9tA/t80t7usYliXq05al8xlwE67Cwr5v3yUbtNp5Tc/dNYxDcUHa5N
LirnXQxkzNIh6t3vTOm5KW6Y/SrnLRB532U+6JsTVOs9wZu1niX/7oFHZgd4s9brqcPRcQ/s
5nJeS5nAucQB3lzOK4kNdAke4L1/oXAEaqJG2E/wCq1Xzici80isyPcSK8SymNQW/11Bh6BJ
j4UbWm+WTaNerDTzJ6KAPf+LtF4r50WWWTbqC3bJVRuhCbRr6nlMdF45ziOu4haZqMzJI6qC
I48a3AsvqudRPq/nzdIpvj0SJdIuxODOeVk97zy4ZpqO7+pzrdylaQG/vX/Vep58hfsg+Iis
qKv8XJ8/TZyxWvKB3bvs55aqotLpAG8Wn5bivAQ2+gvwXvnZW2IG/c0HeOtv6JvdyHPG/sIB
3voXit+4hjqwD/CKvkE7LzXmEaWR70VpWI7TV63+X3DW7wq1f+n8MkdG/IMUHXb+rzDyhq3+
VrDp/byZa47NY9NSjZmqKwJwmIuXVIHjZ/zVg/Z2j03YWEv3dyEqp1lB091F5tdSLzY6k3SU
K/vGoFTfWXZ0GnhJBA3l8w7V6ZvT/ZXxDWFRKoLfnKk99e+uPv+tnP4aYZ/JA7u5yiPJSNHs
4id4r9yL/JemYLHxAO+Ve9ZTzeAZ4gBvlnstFbRgO8B75Z62ZB31SjzACzQF97MPva/CI1Aj
3wvUMMmdS5wpmaI2AH7RivbBeqH3pthIys7BrJXWWUEPi7hoRbWRz+cz59i4dMtqIr2E8R76
1Usrto9MV3XtEadxi03MAkeoNBN3c6kPh52smQU+71SdpaPi26+Wi98dbuBI0irBd7pT+pi/
O0bUG6k0CSOol7XzZsG33eqvJKugp9QnevuZnqH2FE/sZq2nYVcPrpkHeOtdjlwOzeCqPsBb
f0PNsWCBRm0DvFfrVcIHvwd4hda7GAnOIyoi37Hvd9mmYo0pd20Z7CmJi1ZovYsYjzk2kcjR
uXehRs3AcTJZ4ibnWu/c1XmOTTzY2VlkkUYVdnVeovX4IjAmj6CIW2wocXMRXnORztLBJmG/
asECw/m08Po+Tae4uifLMUab0XxpWuTKcxqy8jFNR4SLiOs864paWs0q8ZfW+32s/noiOLl+
oPdKvtKTb93RoYIneK/oq9m35aCHyQDvFX1Z/cuDCpYDvFn0+Y1j0Dx5gPeKvhZztWB974ld
Ifn0QvKNsIh8x8E/1JtWqhGwIIr2Eq6YdLqu7k2RidNc1VyotswChk8uOs1tV0dsU2xipIyp
5NabUQVfBl7jhswXnpJ5REXcYhPazUxbyVT836B5Ai1J1XNp9stH7Tad0mqr0lrWzg0sk4Ql
9IJnzeyib3WSTli8s+8tuhY28NWhydaBl+L7Zqe/BoZaHtjNHXs5RBvYsPfAbu7X49QyGtR2
gPfq+C5JGbWnOcCbC7eWVNCuzAO8+Sn0zQ2jiQoHeEW/XjtPTM0jIyLf8e3PvvCqxfDpMzgV
lHhL0mxLv2jin2RTW5dSVePEHLUDTUtGeSxfNOxNslF2EZGlFW6lomyWHBHyRShgHgkRt9hE
AaiUrP6QKYnCVbAlB7jEF/XjSTrFd22+k8hMtTfY/XhFqwnn0yC9j/m7E1aSNffipCrszvMa
DV4h8b7L6U8JrEQN8N5VlnvqHdUBB3iz2mu+o0ZPwQ/wXrVnjxBx1Bj7Cd5cs61xPoLWbJ/g
zc+hpGgJA5/DJ3iBojhPIPA1eMRD5DuW/SHcRF1RSO6kslfttYsqyySbGHZSo+b/QPso/Jol
J7gXHVSTZDR361oLce3oJyWtGKW6NHXOIxviFpuHqXPpvqMo6mICfHdW+cCcJum9T9MppRpp
rpVaNXDYLUaKl9TzLjYWs3RIG1GzLNkYN/t7BfP+ebG32+yPUgP7QQ7s5koKp44GoQ7w9ooe
M7q8HODNFb2SKmi1dWC31/MKOjHyxG5+BlvqYMvUA7qikicXoxgjFSLfS4Vg667rrGbxZRc2
+VvR0HZZyZtkU7uU5u9TxJmhvi9LCnmtXHTnTZJxzV26cOXojocDO5YU8n79oL3dYxMlOY2q
MWu4OXc492tF5Yv0bE/0Pk2n+IOmvjH377YSPKu6JCb54ZB4/azdvzv+9pu13Gpx5Q1L1Vch
b4G2+55CniQz0LtsgDcLAE3EYE15gDeLvJ4amhfwxG4u40lqcHzcAd7eepkJLZId4M1lPE0G
9w4c4CVlvItZyBEMkW+GdhBb05KJKOOhHUuk3lUZb5JNrT0cH5v2jAvXr6/jTbLRbMUfnVKM
DbTYXVPHy2YXh7YjFuIWm1BtzoVErRXOsNT78jLeJJtSWleq5NsvyWB/wJoyHhNfDGLM0qFm
pFz81nTK6NDtX7OM9yUef2hMTV6hV36yy18p4BDmAG9e+in56gKeMR7gzQLUfEcJh8Y9wVvv
MveSlMBh4AHe+huWLqkraEQ7wFv/QikxFAXa+wzwkr7BC2EwYivyvdgK1za9tVy7aC5oSctW
SNBLo78pNpJYmj2KWmIClqr9ohX35mH2dqYLptg8pty7SamP0z10MmRN2+DFXmdkVtwiE459
vlMkf1Wr61tBZ4GX+PzxVbVxkk48Zb416M1aE9CFcYfR3+zdceHpi6X/X1cR8BzvZfT3443+
egxsYd/JAd5cjqJEApejnuC9ii9yLlATuAHeq/iijsjgwPcAb1Z85hIJjDIc4L2Kz2+cvwCg
ojjAX6z4eIRX8L3wCld8rdQwYaMCH2IuUXxXw8BzbCTlakquXo1dLKGKLy8pOl4sw3NsYq7X
5XjPZNIr+D4sGgam05iUzyft7R6bEG/WtfmrUCopWLGnNW42wuetDLN0VFi5qDV/cSq4u1gl
+ei8mWH67vhCZBaNqkRV4Tmel9XfIsm33eovgjkaeC4z0NsPmP3NBZXKAd6u9jrs9ffAbtZ6
Lo4U9HIa4K2/oOZIKcNu8YHdrPRaMgOnlQZ4gZq4MnXmERTBNzM8JNeuoqq5g52Rq0ydL4z+
5tiEZ5+/7aU0NgZl6yqfv3Lu6TxHJjydWWpuLTL+0PTsRcUwOZ8S4RETcYtN+PyptnAurDGM
8LvY/M2yiXFgKS71Wo2JpJ02fyWfny7P0hG2MBcyDd8k0BrgZfP3823+mt95tA1noPfKPWVf
bcCs9AHeK/dq9m8b+H0e4K33WagnXxRRb+cneLPg6/4xAa2Inti9gq/W1CqYqzDAK0p7dqYq
fB0eSRF8M8UjZykUXQ/WGjoWbCsGYS5Le1NswufPufTetImggm/F3Ftup05yH5Nk2L8MhbOo
UHO9h7UTxkVLBN8vH7S3e2xCu0npRiIaVjBbjZ2vbP5m6YTNX46QM+21GtyAt4IO0cXmYpKO
vy6SKXMzqw1s9XnZ/P1Im784C0Nt/h7YvQovcwoHTXgsOMCbG/Y41Y4aOR/gvUq+c1J4cPkA
by7bWtIMTi4N8Obn0Lc3DTweHOAFQuKxuTlbekdCBN9L7/CvelbJPdeKFifykpX3cjx4lk1t
XXtX6024olMWS+aD++nR+sc0G2UpYhQpEQZPOy/xfjnPh/h80t7usXnmQygV33lntr1JbVdG
f7N0ilR/xJhd43GHo82WGP1dzQdP3x1z4U0kmbOBwfKv8eCf7PNHyTrYcz7Am2VAToTOPgzw
ZrHnKzs8nPHAbpZ6PVUBS1EDvLkfs/l6BcrlAd77F3JodLAfc4C/WuqNaAi+l9rBndjFXith
bIH6Bn+91JtkUztRJu2txwDAViuYi/HgWTaas0TyXPY7A+4e/ZoFZM5zIT4ftLd7ZKL0w1Kp
CLdO1uDU1yXS6GI8eJZOzGxHlnXxxxgtj2xw+ZumQyVXV8RauBLYmfKSej/S5S+nXEFbygHe
XEgRF5YFDe54grcX9BhtMBvgzSpPUkV79AZ4e0FPDJ0RPsDbC3qPRiawnscrWqcunZx5ZEPw
zdwOy7lpI6vFwFaIDbkds2xqFxIViTNysMSyIbdjlo1yi3Y5FxIuJtDj9C/P7eCRDHGLTRTm
xL/IEZPcGtPX9oHdsPubpVPE/02Ww3GogHvmDXZ/03fHShaK1kNuGQ7Oe01jrBB532f3h50R
HNjNGqDFK4ZW857gzUqvp4qmGA7wXqVnvrgxeDA6wJvref6zlBtJywHeXM8rydcsND3mCf5q
rTeiIfhmakfvtfvS3n07D1pGbEjtmGVTG2fy/Z2zkY4GXXy53d8sG805FxPqHR2RW1LOuwzt
4BELcYvLI7Sj+7euRc+h4lYrX+32N0unlN5zc21EXRnMz9tRzpulQ1ofUs9lZIbz8/6abn/8
493+bk0TgHMECx7cBbr4uzwIwaamJ3SvFqGauqK+DAd4sya21Cr4yR/gvZqYRFJFAws/0Vt/
RaUwMwb3Zk/s1r/P5VYSX0GwmYgDvEQTn+ku1yojUoPvxBzUZORroLqILN1XRYhRXeRGc5rC
/D7JRh42y+FIE3MR4MyTLBFeucuFJp5iw0mNLf5Tiu9XwB2YX7Si/kkX9c8RqHGLTU6+3Ctp
YerSGa3m5iX1wnY22/8+yYaS+paOwz9eFQ5Z96vWWGBfmNFM0iksEXtUOEyF4YGiubPF310U
/3v5DzawxjjA28+7wyoNPu8O8F7Fp+WG4jvAmxVfuB6CU3UDvFfv5eafEnDMe4C3/oVFOBFa
mRrgBariYRt5tg6PYA2+k3bgm6LM/qFv1qwIuJeqa9L6LhXfFJtQfC6uNVJcioAeO7Kkcy63
elY5/Jhkw6lZNnaZn3tDh4viohWKT85ExeeT9naPjYs331Zws27aBA3WTHmFRJLTE+L3STau
3WokKWarTIXg0JMVDeIXLjsf03RKCzHeqXQRBUfzZl12XorvN7AfdOlR0LPQgd7eVGboUdYA
bxZ7mqSiowAHePN9NvWdNtrJNtB75V7xW0fgfR7g7XKvE1aAPLBLyntnX3lfgkeEBd/JFWjJ
P++mvmB1jr4ziJBftIKNnub/vk+ykaQc6RW9d3/xwerrkn7Af9Z6/w8AAP//7F3LjiQ5jvyi
EUiRFMUfKGAzP2N2D3vYmcPu/2PJCFceuuFedLVSWVkdwADTB/PutPCHTBRp9scFeIqMy7Yu
HRszt0qSdaRZovUQLs68R4DFLTZYwD8lLforTDk5weIXLTnB7xe7iik2rtpAEKoxmgnltd4S
OnY2ev0+TYdcg1u0bXSyfDLza4BlldT7IgfCXjCbdXuAt7eWSc2aJR/gzR0DWJJ9YoHce38x
CmGSHX4c6L1KT3tRSv6JA7xX6XWN3Nxs2N0T/MlHuTTCK+hOoEArUTsCM1B0sZf7zf2iFYm5
V1pvjo3rtrC4c2UUq3CyTBkXrRB7dn6UO8sG0BpajwM2TJbC/KIlzjR0niVHI7riFhvXbbX5
Y9ZdwRKlPZBgxVHuVa7IHJtICEHXRdC5trg7WbG3JkrufJJllk5MXQtZjII1TpbEZ9s1X2rv
S90HY8GEbB3lCd6rn8yKZe1KBnhzw14tWfPhA7v1HpNKyX5iD+xeDR82PdlsqQHevMvQUi0Z
FzXASxTeeQsVjdQKupda4XjmaGdikmROfVy0gM2jN/Bs3Z1ig/45InNJbWYI6SA8XcGmn4a9
vE+zEaMwCxIW6HnvwSXlvItRKRqhFbfYQGmdEVTbI8sZsyJixYFRxVODnbdpOn5TtFeuYcxc
kzWRNSMsFeQ8UmSaji9FKOgCrzqxNJ3fcoTl72E+iP4w5t7CA7t3jYXmW+9sjtIB3qzztIgk
rX0GeK/S6+GFk41QPcB777Jo6ZrcbwzwZjUaHeNJk84BXqAnfOtyvgKPwAq6F1ghBqy9dezp
9tI1zf/YTpv/3ybZuGyLMK8qnf1CzZoP6pIR0tOK0fs0G78hFbgZdEm31CzR4b7qX9SNR1zF
LTau2lzhCTSUsA2qOekaVy05u70o503S4RaPmj9mj+POrJPLkvi4c9vs93k6FHPkZNCEHpMf
n2ib/dJ6X+w+WJmTh2UHeLPMwwKSbdA7wNvLeZR1oxrgrXfZF44CSXvEA7v3HjctkHaYPsCb
RV4rHZINU0/sAhlRT+c7feEdcRV0J0KgFhOsiM1693/Irbtx0YoD29Nu/7dJNlhiZKFSDBBJ
ukW2rPg+uMQ7z/CaZaMUU6rhCdkwOYq+pjhZ4SIvjkZYxS02UFwRgRqZb8hUk82GcdWSE9vz
KJFZOtyZY9Pl+wloPa2JluTFXZ3YztJhVTRlBNC0Xn2d1y4QeF/lPCiclAADvFnn2Q2X6QO8
Wef1YpZ04BjgvTpPrTRMHjsO8NbfkIBKS5pMH9i9T2FvvpdP+o0N8Aqlx+fd8TTSKuhOhEDE
4hpE7zUjZc1l/aIVbNppr//bJJtagDSa/V1RiHB2SnWJA04/7fV/n2SDxcLxV3oV60k3OFzS
NelC72JLMbIqbpGB0ltjQuVWWwzdJsVEX1L8unBZmaUj3KWKtsiseczC73NZwX6xqZilgyrQ
EYx7s3Slde4g6leXevQZ1oPJ3KkliVPLxkN2W/xx6cmy+IHdu+yjllaTiYoDvFl8WnhZpz3+
HLv1DiP4rxLpS8nRnwO99Tf0HbwrgqT10ADvlccSrYDZ8/gDvEJ+Xli+0AjSoDvhBq2oKUPV
3mvDZIUh6qYrCo18bnw9x8Z1MRGLS1B10Z8s9cdFSwqN585rc2xqoe7qBnxX0BGzRyuTuRN/
VDh00Tc4YjRuscGC/vxinPSjtXRkC66Ym60XGSdzbEJ5GTSLsWauvWdz+dZMhpy+OO/TdMhA
iLorUAZKO1+/Mk6WCb2vMvnL1sgP7F69R1SMs11lB3iv3hMu2VPvA7tZ79VW0LK5CQO9V+9Z
Leif0pzeO8B79Z7WojWpSAd4hd479XvwVXiEadCdiINWGvWq3GIIUDlr6rxkU8ync81vk2yo
hLeyAIloHPsl9d4K43fXe2ea4n2STS2M4a5l7KR68hCoTrbu/1EhXZg60wjTuMUmpJsCuebr
ZKZpvbeielrh3PZljk0oN4lz/xigZ03mJ0aRcsWjdpF0MkuHQfThMASdsoX615jIN7b4kwLp
QLaB3iz2asl9JR7IzTJPCmnWMOcAb77D2gpnz0E+0Ft/xbBnphtWzrR5ECiGpCPKPT1RHeAF
3/dLw5eRD0E3szuqdoCKqlaTq5VftKIQxnrR1DXFhgpV39kpAzHU5EA5LYnHRcOLtv0pNqHY
oqezSmOtyVOpOpmncMPdj0Y8xC02UMwqRKOvSqvpkYoVxx4u8y42FJNsWJtviyqL7ywkmWK+
qH3wPG7wfZpOxA36+w8Y8YnJQfrZuMGXzPuV7P0Akp+WD/RetReeM8ld4YHdq/ga+qqTrewd
4P2avkvyzO4DvVfxVRcVmuzFHOC9ms+iKJtM0Brgzz7KHQkRdC+9Qyn8/VocFtb0Ue4S05RL
zTfFhkqNdjWt1JUeARS5o9wVGcadLzTfFBuXb74QM0Y6RMN0XtsSk5FLzTcCIm6xCfnWIc5x
hRny/jywoGvgemZkkg53JmZjcR2rlO29WzMzAhd2Q5N0qPm7o1Gw9M0fpM9ypz5rL9H3pS5/
VqKlIuny9wRv7tgLq4Zkp9QAb+7Yq6VhVisf4K13mZQKWLLrcYA3i/mwVkh2+z+xm59CKx2S
J8wDvKKwdzUuMqIh6F40hD9+0MC6xEqVFRJLhl9Yz46h3ibZYGm9xZRm86eCk084LrEXQaWL
Q7VJNsIuv1nIADAZmIxLjggrynk+DI1kiFtsoDQ1QiMnpB2TU9uLfP7OzVLepun4ZiJKYWIt
4i7Slb01B7gXDXuzdFx4V0bl6A9N7rBfwR3f2+evZhNaBnjvKlt7ManZzI4neLPWe+TDpo3+
HLtZ6fWSbYQ7sJt1nv8mPVu0fWA3P4GtWFYpD/CC7zue+rj+R+ORCsF3rPpricQsaOSrFrWk
yYhftKL8xRfGa3NsXLJpV4PH0Zqm60UrpMSlzptl4wpPXYeTAEv2c7JI57WzctHHk/bjHptQ
bDFwClRBKiTNkxZ5/J07prxN02H/6jx0Hiha0oFxlZ/zhZ/kNB10jaemguivUFrnvRr1/rrO
2+/xB5Scyx/gzWWUGkeIySrKA7u9lOcfseSB6AHeK/A6x2FDcpDgAG+WeFJqS0aEDfBmkcfF
F96syHuCVxTzTj0sfOkdwRB8L7RDgbSCuYpI90L4NQvIiJ53yM+RwRh6URIRI7BkLERctOLA
1s4P0WbZiCvWqsy+RZCktS4uyZircJH1zCMV4habUGuqUqtYa0TJHRwsedRCVf7sUbtNh1kQ
mLEJdciyWSTxzl2GptmAcqVHonCzZHvrS+J9Z5c/jtbxbCnvCd67xpIUaNk+lQO8Wet1XzuS
wwQDvPUuM3B8p3J/4QDvvcsNCnAywnyANz+HVsKwLPkcPsErCnp8Pg7JIxiC74V2KMZgpzCT
WfY3XyOPrkI75thEaEcYUxMagGaHjtaEdvRT6fo+zabFVKchNOmctECOixboiXphtMIjFuIW
G5dt1dQleEcEheQyA2sMqqld7Csm6XAc2KL1uEGW7ARdFdpxGm34Pk+HfDkXAu7Qe/K0LK76
HdXepxj9YfJHxRWnj9/a6o+SX+4B3lznwYJZk7UB3qxBzXdh2RmRA7z1LiPEnesta/9yoLf+
ii4kCiZXqQO79e8jqQUgqdgGeMGH5WpChEdyBd9JEwizP/+3+qKjFYhzdZO4aEXB8cLsb44N
lerKQNhfeyGWHBu/aIkG7edJD3NsaiGRDrU9alrJQ+U62bR/w+yPR27FLTb+MXap5rqtOiVM
ppMuMvujdlFvnGIT5i/gyx8ZUiOknWZ/URP82aN2mw71SBWhhw9UtlE1rvodJejfyOxPSwfI
LbQDvPnsEQpkNekA71V8wsW3b3m/vwBvVnyuhMmS4SIf6L2Kz7C0ms0/OcB7NV+rRbLV5QFe
ofkuDP94ZFjwnWCBVhp2Rm3id5k0txK3RQMjF4Z/c2zCu0+aCwpQ1XQfhe8MVzQSXhj+zbGJ
iMnIbvVtYaS4pg2el0wFX2m+EWFxi83D4Lk36/7NQ0ieHa0yeL4w/Jtj8zD8a+IvJKI1SR+Z
L+nyhNPjh/dpOmRs3WqP7VJLKvKXwfO3Nvzz1T1rB3egtx8yJztrntDtUk8t+wMe4M33WH1p
o6Si/0Bv/RUFuaAkhwcHeLPUC7fGpMf4AK9oJ7ww/eORF8H3sjzMt/SowgCEybaoDaZ/c2zC
9A9F4tNkkHWqjotW1FxOx0/fJ9lEpQ7IhGu0rWUd7ReV9y4MYHjERdxiA8V6t6b+NWH///QR
8xLXP+zn+dSzdFipV1d70Fzl513/lhwxw3mW3Cwd8o+LvzvNN2D+DqVd/6ak60vr/Uquf5Y1
/vpA75V8Uot/B5OfvwO8V/a1mJzOWlEc4N33Odqv0rLvQO+VfTXCq5K/4gDvlX3qjz9jNtLj
CV4h+05NXn0xHrERfC/SQ6H5hx4ebV/JDYtftKDucn2qO8Um0ti6YofIvM7GRsRR8GdX+KbY
PCp8ZP4vDj+2dNfnmgrflewbqRG32ISAowjz4AatYtoob5HsO7s5b9N0Yq62ViHfGoer0lbf
P74YS5+kQ87HhHz7B+lDqpfZ87f0/etFskEKT+xemYe1xI4qPSkc4M2te64tKSmhntitdzhC
xHw/mvX8e4I3V28tqgDpyQxb0fp46xnshbOtwAO8ROBdtO2NwAi+FxgRWgjs0QPfsu42S8YT
rr1gptiErYvv7EAY1ZK5qausYPiim3+STKg6MTNgfwOT02hrUmCvLP94xEXcYvO0/Ovhgky+
k0iOXW2w/Julw6Ti357oeG01WUJeY/lX8bST432aDlmPeSvsfouyJYqX5d83t/yDpIXRAG8W
AVgAk304A7xZ6GlEc2TnhJ/gzVJPi9XkXR7gzX2ZERORnQY/wHv/wsr+dUz2EjyxS6TemZ7w
FXjkRPC9nIjozbGI1NKKyVnHZbZ/FwvwFJuw/WN91FeEOW2i0pZkeOhFC9UkG9cS0CGOb13k
ZwNtZUlu25XB5EiJuMUmVJs08l1jB6ycjgb7fNu/STrM2mpzfUS9QzKpc4cnzCwdULAIPHTR
p5COJHl5wvx1rbff9o8paRMywJsrKVQMk+XGAd5ezUue2AZys7yL0lJyLz3Am+VdLdkuwgO7
Wdz5spNsyjmwS8TdRYP8yIfgm9kdDePIFLFpcogwrllxTgsX2m6KDIZ3oXUgX6UqJY8CcY15
oavj8/V2ko1/WUUY2aBL8tQ5LvpsbTfCIW6xeVg6V+psrftOJ+sZvEbaXZXxJtm4BmKwsOZB
10NpLfTZyR3TdADQ3xttzKR5g+pXGW+BtPsquz+pkmyGOsCby3iRdZF8FAd4s8LrpUnyLxzg
vTrPsFjW1HGANzdfkn9Fki1vA7y9nKyc7FwZ4CVa73zsVkZGhNzL72jUGmujyGfKNryWFcmC
l2Jvjk3oNm6+BPvqa5SMiFgk9pTPm/Jm2Yh0I1SkLpT1Rior3tZa6adP2o97bMKl2WUeWERn
A6UnO1f0f1bA8/aAWToszamoxIktJW19wiRwAR3Gc7U3TQfVUKX6goRZJ1O/akoAfLXa26fl
/uff//r3//37X//9z38gwD/+87/+959bF6rc93z35EJyZmHBR3mBFv8S08OqBbN2tQO8VwGB
/0cleSsHeLMSN5cpyXrPE7v1HkevISeLaw/o1l+PuxXMWn0M8Na/kHwDaj3bjnCAF3xSEM/j
VWRkeMi9DI8G4PsYIyZMzl7ENSvO0i/GoefIUPEtd2vaWaOyl9xmlrrkLJ3OR1Tn2NRCWtFq
lxalhPQ49IqB23oa0vbxoP24xwZKlV7VrEVIkCZPyvyqJTsKOZ+LmaUj1eU39IgjAU4OlK6x
O/QdxXltf5YOheOpb478/qgkl66X3eF3tzuskY+btTs8wNvP1ZPn/k/oXp3nS3vLhoMM8F6l
x1os3Xx6gLf+hgKPobxkA+8B3qv2Wi+abCU/sJ+t9UaEh9yM8ABCX397bZCN0F4k9q6GoOfY
xBC0hI2Pipkke/MWDUHbRTPbHJuY7mcmUSSsqNmm1hXGD7XS+eG6jACPW2xCtjUTMDB/3rRn
660rlHgluqi3TtIR6uqMWLU3TsYtLPM5PM9LnqVDUQcX4Gh/yMZQvk7Xv63PIQKG3VHyYHig
N+s8lx6ctbU+wJu1nvgWNq31nuC9Wk8imSQ5YDnAe7VeFf+KJNt4n9i9Sk+x9JqsLA/wkrP1
ixV4RGXIvXAJ32ooY3dtpJbsq8E1Z+uNzoZu3ybZUKijir1Br/Y4gMz5HC4ZiL6IMZljUx8+
w01beB1i8vS2TtoM/6mwdz6OJSMp4xYbV22ETAA1hrEwaWMKS6xqa4WLbcUkHRd50KAyNuuP
1saNhjcXPoezdMg/LmDE3eLVedkc7pZ6X2JziEAlm5I9wHv1XuUbziMHeHOrQHhQZGMSD/Be
vdd6sWQZ58DuVXsMxTRb2TvAe/VeN79tSdvkJ3aBoqh8ofZGSIbci5VoTar6iqXISNnRjCVD
xHyqXd8m2dAj8iOO18Sw546iaIkfINqFu+EcmepfLv+NwkVWELNJnZNDqn8q7J3bp8uIyLjF
xmUbk98WdW2EAslDaVhSda2PfMnrJ+02HX/QQuqhvzxoPe1+s0KKP4xVr5+123RIavcbhFIh
HEJf7obb1N5ud0PppYtl52We4L36yax00+Qp0wHe3KVXi68wWdubJ3ivjm8WAyZJCfrA7lXx
HEfu2YrjAd68z4i29+T8wgAvOb29qLOMdAy5k1iABXsHv8scibGaNQVcEuvWrqZlJtkoqCn5
/7Bz8juGawy59bQ++T7NRrhhzHiTNWvZQe8lo9H1VLJ+PGk/7rFxQQCE0XlYfcsoyXp9XLXi
9PYiD3GWTpyrd+7WTbAmn7VFFodXKXXTd8c4DNN9t6y1pW1vXil1K0Tel8xGN/D9PSePzQ7w
3lUWWpTNkzrgAG/WelqSdiJP6F6dp600aEkleoD33mGB0iE5mjfAm5WeFm3Jw7QndsXJbbto
lB9xGHInoiAkW/fNuwsjaZA8Tgtb0xW1vH5RYZlko+HFC6bhy519whdNRV/pvEk2wuK7aVeu
0rMZaKsscE7NGj+etB/32LgmQDbjLjVyfNMRaGuGos/dDWfZMCuRcnfxqk5rp7shn2733ufp
+BeUw0UztqTJHezL3fA7uhu6ZEvPOw7wZn2HBSSbqnCAt9fy0oe1T+z2Sh7VfCXPsZsreTVO
N5N3+ABvr+RVyo5BHuAllbyL+soIxJB7gRgYgbDEGuY36XiPJZW8S9+bSTYxNshh4dFunD1/
vsKbZCOs7AqiI7kK31zJu5j4GXEYt9hETa7WTuzao1HW/H1RJQ+uhm4n6TBV681ADbGmC5O8
otWQTjsn3+fvjvmDFj2gbD0drfcq5K1QeF9TyKMCWRfrJ3azzLPSk4FvB3azyOslvB3SBocB
3lzIs2LJadsDu7mMF2ewyVLyAO/9Cym+cMlP+wCvKOTpRa/UyMKQe1kYFbr57xdRsDXbZlBW
CP/rQt4kGwWirmCuWhGyovXzZd4kG5d5PQJtsQMlx22XFfIu2j9HEsYtNlGTM7GqVrGJpNvY
VuzgKtqFzJukwwIuXBEqt9rSQwufnlMyTQcsKpLkKhxq3q3xt6zkUVrn3Vg0kucKS6bblk2G
7Lb1a8WoZq1enuC9Kz9qyQ7DPaCbtaeVljbNOMBb73AlLijJUc8B3vobcvc9jSY3GAO89S8k
3zRAyy04B3aF9jzVN64IRlaH3MzqaMw9XF6QW7IRfI1987XVyxQbKrWGy4svodIlWTClJROm
2PuF3fEUmzh88DfPwEUbJ/s4/Zol47JXteyR1HGLTNj61YY1+jiFW3LkMK5a0it4MWg+SUcq
otTew6mrJdtJYE2AIcDF8NEkHVJh37GRWGuYXL1etn7f3tbPirWkEhjgzVUeKlY5q1We4L16
LzJmNHkoP8Cb9Z6WcKVK/oZP8Ga95z9Ltrl/gPfqPZGSTcs6sEtqjed6r424jnYzroN6FxMG
iWJDVu+t2BDzRcf+HBsqSNx8k1dd8CUfn7hmRanxwlp3jkwtNUo/LpPMJV9yNqSuOYKteJ6k
0kZWxy02odz8Swe9YRfMTx8ssXG+0nuzdFzvAQOyS2N1alv13s+ftdt0qNcKlZW6a3LLyteX
3lul9zY7+4FZ4XRVaqA3S71aLHvqPcCbpZ745zY5vTLAe6UeSwm7hWR33hO89TcU9AXYJVyu
t+EAb5Z6VjDrODTAS8Teed9+G8EQ7V5mx2OcUaWpy/rkTI5ftILNVWjHHBvy14mhVzDttbWk
Gc8SfYTK535rc2xcuGGtriKxN5f56dCOJXYv9YzNx5P24x4b1221mmLsHCvWZOU+rlpxsNzP
fZxn6XCLd0YMoXPN272ssKXG06z092k65C9MTEzTw4wnfew/tVF6qb1fx9zP95Q9aSX1gd4r
+riX2CUmBcsTvFf0NYwkieTieYD3ij4JI7RkEsATu1nyWbGelM0DvFfyNSuPQcOMonhiVwi+
ft7G30Y4RLsX3CEKqLUbV4Jk9HNc9MmnuXNs4jQ33PDCKkWy8pWWaApUOLfjmGMTH1fFMJAj
6JCtxpf62WbObURD3GIT0s06UaMerjyQLSAtMXPGflHem6TDiuofRiH2e5/cXCwSfP5L/uxZ
u02HfBVSIajGzdKhcy/Bt2BiZL+/n7/eeX+/AG9u18MSTunJhr0neHPLXi0Nsy7YB3ivlG+t
qCRTTwZ4c/XWSk+q5AO7+SnsBSg7s3SAFwgJbOedVG2kQrR7iR3YrFYEMt+zpX1fcImH81Wp
ZZJN62joq2+4VyRP2OOiBWzswlh3lo24yvO7I2qUdUHCNWGv9aI5tI1MiFtsXK75VgxNOtTW
q6Rtgpf4+53aFb5N0+Fqvrb4HriZ1aTL16KpYDjdHr1P0yHzPR6HXxIzJl+d11jwd/b3c3GU
HBo9sHvX2NpLVMyTzhtP8Galp/51Sjs5P8F7lZ7GcpCcC16zctwq1zbfQGTd/Q7w5meQCkNW
5x3gFcW8Cx/nNgIh2r2sDozRjAjiVZJkA1VctOT09qKYN8mmKbqQiHIem25NHtF6sfZOshHf
ZXFVVpb0vmxNNxheNYWOOIhbbEKxiT9iriI6hfPxVoO/etEoMEmHqVNFFvL7Y0kTg0U+zq6W
f/as3b87EaNCrarTackZ9FcK73c0+BMr/m1MnpQd4M1llFp6T4bbDvD2Yh72bFnkAG8v5rWs
x/QTu72Up8nT0AO7+RnU0jnbMnWAV5TyTmOlfOEdcRDtZlSHRlpVMyN9qJSNpbxTGfE2zab1
BlGHkubrVJbNEntt5XPTtVk2QtEiD1Y7aTbOe0Mpb4RB3GITpTwVDY9twDjp3Grwhxe7iUk6
XJ97CajJXuJldbxz25dZLtQNIhdZgChr7v+q431vez+CbN7pAd4sAaRAfuz2Cd4s87oLj+S7
P8CbK3lckolnT+j2xkuU5DM4wJsreVJaujP+AH+2zBtpEO1mUodiQ6ikXR9r+06Zd7H2TrJp
rvO4Rp+/ZQc7d1TyJtmIv30GqiwImvZxXuPjcTF1O8IgbrEJwWbkr6qJP20t3Za3ppInF5W8
STrMIOR7CX+/e3b+fk0lD81++qzdpwPQKJK3KzGnz59/y0Lep/j7Zcf21kzsLRsP2e/w1ylp
lzDAm5d+KJp82w/sZvFpj7T2tMdfgLfe45iP7slBrwO79RcM076aLKoc2K1/H3GL3yR3jDzA
K46Rryo/I6ii3QyqkN6aidTmuiA5DPb5Dn9zbMKsj6P1UbQ2TA8BL3H404tghzk24fCHfolI
67VlQ3XW2DFfWfy1EVNxi01YvqA/ZB2Ue892LGyw+JulIxXJH+Fq0NAkO9P86RZ/s3RI2e8O
+i/la2bSmB0mE05/dfX5N7L460WyXeIDvLkSBQUwXYl6gvfKPeFSk5lIB3az2JNimJzzHuC9
cs98DZbkqdMA7xV8MRht2SHTA7ykb/A8F7iNyIp2M7LCV6yYzqy+CHO2027FweW1xd8UGypo
LUzkkMPROfcE0ZqU435aO32fZBPzvMC1alNQyobXLBoCvvL4G4EVt9iEdGOI03423+Em582X
Cb7z5JpZOkLhXaMxj0SSTtJdcuR/6fE3SYc6NHi48igk99ovi79vbfEH2JIF0IHefqwcG960
UAnwdqkX83tprRfgvWKPyTV6egTjCd76GwqGk0Cyj2WAN4u9Vrol16sBXnG03C4s/kZGRLuZ
36EuIZsSVc3acCxyfLm0+Jti47rNmmHtRsLZtLUdFn9TbMKbOdJVxKw1Sk5VrLL4o58+aT/u
sQnHF3SpR+jKC1raRG6JxR+cFivfpulwYxKt/t6I08pqV17hTw18MSQySYdq5FFbb761MEsP
A0/dnZfa+5Us/jib4PGB3iv6pJaWnsg8wHtFX0NfeJKtP0/sXsknULLplgd2s+Cz4gtC3uAv
wHsFX5Piy1ayuneAVwg+OD/O1ZESoTcDPISsmq/CIPmp4BWBtJfHuXNswq0PjV3/UyOm9HHu
Gou/8+reHJta4nxNLQacO3La4m+JidzpjMXHk/bjHpuQbkquXiO+AzB/nPvZFn+zdFiROkX5
1bgl6ySLLP4AzqdGZukQIUNkhlNHTFvzvBz+/vrQyG6HPyuYLqcc4L0KD2u+aDbAmxv2XFZK
tvP+AO9V8q0V1GSTyQBvLt5azEonz+kP8ObnUAtT9i88wEvOcM+9X3SkQ+i95A5s3LsSgPRs
Ftgq75d+XtabZdO0+bYTw+JPss/4Go+/fpqq8j7NRipHqFmNgZHk07ZoYuRqMFhHNsQtNo/B
4Gg3a901eD6X99MHg2fpcFV9mBViD/+kX2U2eJYO9d5bt5iAsd5fHn87Zd7XzAZD0WSc9IHd
rAKwQDZaYIA3az0tlO01G+C9Wk/9vmWnqwd4c80WSrK5/gnd+9fVG37dA7zk+Pbs++6r7wiF
0HuBHSi9ASn5mgXZEOlVOu+8gWqWjQL08Cozcn2UZaNLjm8vJoNn2YS+U2VDMkwqibhoRfnr
wuNPRyTELTah2Ji5icY5oaRNUxbpvDMR/jZNx7n4c9ar3/gY0MjqvBWth8BnPbvv83fHmvl+
L9wXNX16+3tOBv/2Fn+9Zs/KDvDmKgqV3pL1xgHeXs3Dnux1emK31/KAswr0AG+v5UHNKqgD
vL2WV7Mj4E/sEoV3PhSpIxFC76Z1qDZhih5CyJ3TbEjrmGXTOoKYYqtGWTKfHtYxS0aqqgFr
A0n30Cxy+OPz7D8dcRC32EQhr0WrIbRK/o9ZRfT5hbxJOlybKSi6MPIHOX1c++mFvEk61Dtw
NDI2zRdZX2W8Bfruqyz+GmDuJRzgzRJAIyUwKfMO8GaZ10traZeVJ3hzIY8K1eRQ4gBvL+Rh
zYr5A7y5mMelc9LzfIA/W+qNUAi9G9ghVqFpw3TDxg6pN8kmTtEqoxpC9kRikda7LOZNshGs
bMSGVl1L7izmXdn86YiEuMUmVJsKhUF1D1PJtJ5YY/N3UTeepMO+PQJwFenLICSNDDYEdkzf
HfPNHph/BqLm+rcu5tXPsPlLOiVtDrpNqr0lhzcLhPHXWA+Gjkx2AA3wXjkCrYSBVU6OHODN
sjiKwpp82A7w1rtcrRWj5OswwFt/Q7YwjUz70TzBW/9CiqjulpTFA7yil/FUSLpYGUEaei9I
wzr2iqrkgjLtfm0rhOTViPIcGyrVlVeNir0JJf3d/aIlsrhf9DJOsakuVbCiSxVBkqTFVZ2s
S/2pyHaxARtJGrfYxDgroD3NyVWSMZqzQ7B/rOjK+YjyLB2p4dQVdtHgdyc747HGjwbOzS6n
705vxL4YSa2mSQeLVxH0NzAg9G1qVvI9wdsPvKUnBdUA75V8wqW1ZPLzAG+9y4S9ACc9xQd4
628oQIUl6Q8/wHsln/qNyzo0D/AKyScXo6MjVEPvBB3UAtJIlYFF0kl9BdZEF19Ivik24UYp
WEOwiCbLun7NCjL9dN7jffrWuDiS2loMSJBmLadX9B+j2YXiG4kat9i4OuDqAglqQ/YHLj0f
saJySKdtgG/TdIQrdcDuEkksubuIq5bcnZ8+a7fpRLi6AD4q1TV5hvC7VkL/JhaE3LMnXwO9
va+sW/a7d4A3iz0pmC3vPbF7pV6NdIjkMvjE7hV6VYtScrpmgDcLPS2YdWQd4CW1vfNkOx0B
FnovwAIimouYMV3ai2sWkGmn0uhtkgxFPFfXqIQRQc2VW2hytfpTd+NFuWXy1jABCkqzTkBZ
98El/XP1VBl9PGg/7rGJ7sbKTdk3tmCQVkZLnLMfMaPXj9ptOqyutyordpRsJ61ftWBH6vuY
c6vpWTr+CTU1/woYUdbgd1aGv4Ter+M+SPnD0g/09vYyrsn5sAHe3DaA+b9wgPcqPm6l5vKC
ntC9eo+lQM99QQ/sXrVnLjEtOds7wEvU3oUrzUiv0HvpFcjySC9tzNnAnoIrBnNYzzry3ybJ
UCH1Vc5XYEweFNJkNsIfT3HpTE28T9+X8DJuLieAe/KUoK5xMsZTe52Ph+zHPTLRpUgKEiov
ega29jbW01PPt2k6bNSxm7/Z3ZqmQ39XCFc+nbt+n787Dah3VbVmadfsOUPfl9D7UtvBXvw+
J8soB3ivcDIr3bKJpgd4c6teLS3tRPPA7hXwXf22Zeu1B3ivfOeId0iatQ7w5g2GK3LLmg4e
4AUyAk/DyXzlHXkVei9LhFBrqxSOsjUp+HFJ9xS20xmJt2k2LiKcB2jn1tKmg7pARvhqf2EQ
MslGpPYWCTLILVmbXGP7XStdzCqPtIpbbB6RPy4duQkac/LlWXVsexrC8zZNh8NDDH1vRFIh
3ai3ZH7l0oxm9u5Yi+8okLGvma9T240a72uGlf1LAblN8IHdu8RCi/9mfiYjwJuFnkZ3a1bp
PcF7pZ7r32rJNf2J3XuPBYsl+wcP7GaZZyU+h0mZ9wSvkHl0XsXrI6Wi30sQ8UWqxvyof+Kx
ZoXREn+dK5k3y0bBlNSJkCQtKzeovFkyIo1RW++sWZPV6LBYoiN++qD9uMfGdYTEyHXvgMQ1
n1ExnrT/BwAA///sXcuOJDmO/KIRJJKSyB9IYDO/YjCnPez0Yff/sWSEKw89cC9ztVJZVR3o
QWMO5p3BkMJl4sPsqyQHZ8MR0e6/mMdoSctoYnKN5CCdK9JMh5O1cs/a4z0AKlP5U1M/nRfN
+07NwRYXLnCWcIA3M7ySMmqY9MRuT+Qx+gEHeHMqzzmbguMNA7w9lUcCyvkM8PZUHmf0Ex7g
JZXa8754HR4Ves+jgv2zkVCVarjcyZw71B2ONxmNczyPx291Fd1AOzjeZDA1pkmi7sxVK+zY
vITj5fMGUB0GFbeiibOiq/93m1pWqTDHW5L6uhi5nQ1HWGIaOnirk1ZYiWaN6uB5tXZ6dUzM
LxTO9IQzWMx7jdz+yrqD5C8+sNoxwJupniUT1CzuAG8me5r8xYyaxT3BW1eZMiczWKTmCd6c
zhP/o+DU9wDv/YRMya+/qJHNE7yC7NEF2RtGFXrPqMJv8WxWOZM1QhkFL5nCuCJ7k9H04lyv
qOQGv8kWsb1+KknyMR2Nv2QLNafi1PG1WcT2zuu2OmwqbkUTjVxUiZ2N+5braGVwhZ27k73z
1rzZaKRyqb7JnPQRgS6LqxJ69SKhNxtOvFyohPpNUbCe97sm9PgrdAfBAt+K0t6vrPBXjHGF
vwDvPfhLTw1UCjiwm+mnpU5oJu8A76WfyqkbKutxgLd+h+J/lFH3zwHe+gnZ7w1GqGDOAV7w
WqGLhn0dNhp6z0ZDrYqJ9lDMKWgJ1laMzVY5952Yi4ZDf4o9oKxZwBuWP7MicWrlghJMBUOR
Bq65CDMHy0Hl/VZks64s7HR4aNyKJlSvW1b/qarvtw4uzqLJEG7n4+az4VQqXEyL/7QLwbnG
JUbSOZ8rrE+vTm/sv51sQr3C5fG5maqfnX7+jeT9LIVvOMj3nuDNiR5O0TQNJnqe4L2Mr0qq
Cn6HA7yX8VkoQ6A2Igd4M+OrvrXACscA72V81S87CqpiD/BXM75hpqH3zDTUSifzRS6igia1
Vrgwhn3W+Tk8FQ2nws4m/Cj2iCpYmPCHVlzyu5wVZD8mo3H2VnKtzcmkWu5YPZbWcKSrYWAd
Vhq3ognyJq2V8PltuYNphUWUr9hFxnEyHN9fVGsP6Rd4uHIN5SuPScnrvXZ/dVSYwiCohFsf
XPx/Ub5FlG9zj1nJOamC1P4Tvb2sh9qBH9jNXK+GdTku7xfgzVxP/agGP+EAb/0Oa+HU0MHv
Ad7L9VpOrYDF5QFe8I4/P7L8BB4OEXrTvSNMxsTCoutR7cWyeytOrCsp57lo+NGY24yqcwrp
sO7Lilxlp3OJv7lograZqhOVLoqKH9Miu4ty0Uo4/CFuRZMT9VKzL44zidIrqpSyQm6KyoV/
4mw4vtEaNao5xq1gjz5ZEk6/aGSYDMeJXu1E0ihE3ODa/1Qu+cX1fh6Jv9DlB1NTB3gv4YsG
PFBA88DuJXytJFJw+GaAt64xZ0uKdloN8F7CRzn1ihK+A7yX8PUSKs0g4TvAX034hkGE3hHt
D+6WtfUe6RaGO9aWEL7Lcu5UNI9ybqdoQGCSjEWzqJ7by7nO7lw0MVeW1Zl48AmrqHnHCvpK
dOrJ/LnT3u5F49RNS/iqxDBt85cKSvhWiCAXvajnToYjnSqZE6RuBRf6W8H3zgd7PqajYW6d
nee30rLCdO+l6PzXJ0f2C/3VBqbWB3hzx15JHffseII39+xRalJvKP3JCs+eW/PBlGpFLaoP
8GYin1MG75UHdvMu1Bj4RXfhE7yARnA7q9v4wTusIfSOXL/fMfwXUjXXzkYNFfpb4mErV4mW
yWiaknKPYWxRWBpvxTW19FPRlI/paCrnUKYmYc1gj21Z4/l6njX63Glv96KJrJGvTgyj92YZ
dIiZzRr9uWXvdNLqfTqcsLlohVqjYgSKzi8bD75o2ZtdHfOLRMuS6bn4r+ngbRzvu4T+ioJt
8QO895Cl6HQHc1EDvJnq9cQgCziwm4mefymGfsADvJno1aSCyjke4M27kJOBBuUH9quJ3jCG
0Dtq/cHZyKKFqhY10OZiFdE71ad+n46m+QMtetdLU1SMKbUVc8562tr2MR1NpRzzmtlUUHHT
sqr7/6J4O3whbkXzTBd18iuP5WaKZr/W6MDQRZ/AZDjBvrv/ZJhKxWu3K6IpdhbNx/zimBM9
D8hjiTvfS9F5H9HbLPVXLTREwVzeA7s5iUJJVcGz/wBvT+XF5Q5O5QV4M8NjPwlBFj/Am5sw
LVkGP+EAb0/mlQ5WlAd4Cce7SLEMZwi95wxBVqT0HqpyYEdbWeKLWuR0xPN9Opim/g+3qlwJ
NZZMbUU0l7m8yWjCFcJpRKEHC9+Zy3s4/l5vtLd70UQuT4mJVUh6xeWcl4RTLm4Tk+EIaZfs
70YOqwtY/eXLc3mzq6N+k6+1V/MrBdjp8Erm/dpSf4q25g3wZhpQUyaw9W2AN5M9DW1ZWOnP
sXupnkWPN1g2GeDNybwe48hgLu+B3ZzKazFDiObynuAvJno2zCHsnjmEkwgiYuZac0fTX2uY
np27KcxG47cSy1St5pxRsc20YtLoMpk3G031S0I1eRjXgo15a5J5xeyHO+3tXjSRlis9i1Lz
kApMjZYk84qddU2+T4cjHEUO32lVrYPn0TJ7tvPOvOlwMhVfH/alzwyXbX/PbN6X6PwVVH1t
SaVk2YTIbqW/qMyBegkDvPnsz6nDZbwHdjP7NL+1oXmBA7x1jUlLKmiqcYC3focP8T50JH2A
t35CdtYraMfAAC94rRQ+LyfbsK6we9YVj2FT34nFjzWwjBQPLYjmajRkLpqY8qhOBYVZaoZ1
X2iF7ovqef5nLpoY663drFqvkkFXvw1SfzaMK25FE1J/3LSGh02Bff3ymkmXK92X2XBiBNi6
E+rSWcFi/zKpv/NZ4OnV6dVvbo1Uul/j4PvBS/dlFdP7Lqm/3sFUygBvTkbllNGU6ADvpXxV
/J0Lqmg8sZsJn6aCOqA9sXvpnnGqoFflgd1L9mLNCMyHDvACQuGb+fwIHs4Vds+5QlvTbFS4
E+Nkb0W33ZXI31w0nIrFUHhhpZ5Bqwcne0uEXy7mgOeioURWVbK22gStr6waAz7rTvvcaG/3
ggnWZuqEght3qQaziTWyzmfpuffpcCrn3mvJTTpluBNyTdX/x1vt/upoyX7hi4lpQYV+X1zv
l9X4y2ahmQAmpQZ6e10Znlca4O00z98BYB3oAO8lelbDYBdV+XuCt36H/gZNHaTKB3Yz1eup
drBSMMAr8np23rxvwybC7jl4WI72way5soAnlj+0wnLtSuNvLhpnbWZas9OJ5psWpXprNP6u
qn1T0Tz0nKmHR4Q2A6fj13AjOg3mc6O93QsmJ2pa1VdHizNJ2yrx9zD2vt5pt8ORJi0UJWOG
VsBu4nhqSWH5fExkNhx+6Ndw8x3XGM5SviT+llG9b5L4K6nD9hMDvZfxVUrN0C6uA7yX8YVy
XwUF4AZ46zpz5qRoL+EA72V85K96Bld5gPdyvtZSSHOAus5P8BLOd9HjNXwi7KaHh0q2Wmvn
mBH+aWq5U9GEzF+L3JSVnFGfmlUyfxdWWnPRkBMethLWYIV7BcsZa1gS8Zk+z+dOe7sXTdC3
2p0p1VJiHB2lFV8u8zcbjnQqnSmUGMOieq/O37mHx2w4HA4e3VquYgUcIHuRvl9U6K9RBtVf
DvBemhcDv+AHPLCbG/YovGzh0WDH7qXyWlJVNO14gDenbs2Z743J4ABv3oM9tQam9QZ4Sbve
+cCmDXsIu2fdQb04K1K/abSMy/wtqeDqRVpvMprWnTiKOJOA7RQWyfzZqfbxx3Q0lSQq0aIx
Z4FW19c0hJ1mjj532tu9aB6Zo9xyNpFeUZeYDaPBs+FIENUanYcxTQvn9b56NHh6ddSasP8m
TdHj6zUZ/GvL/Pk1GFb5c+xmEuB/s8OOvE/wZqLXkwhqdHeAN1O9nojAksMAb27GjNYAVLX7
AO/9hETJBONFB/arid6whbB7lh3UTJvGDV4znMtbQ/QuNGBmowml4FbIuUSw160aMFdEbzKa
Wqj4XYuZSwcdAeOhJb16P9xpb/eiCcrGXbJGKJVAeepVRK9e9OpNhuPXCYo4qCsXMNO6Qedv
enXMF8dXppmp4bKFv+Vk8G+v82cGqtQN8OY8CidVsCA6wNuzef5SASnUAd5M8ih1VLxkgPfn
8zJqFnyAt+fzKqOO0Ad4AZW4UnO2YQ1hN207NO7wrK0ZngH7ctuO2WiaBjHyy2e30tAM2Jfb
dsxGU/1+5atSfHUYbqH8ctsOG8YQt6J52HZQryH3V0sBtYZ25PMmw5GwFq4UkxlqjNY4F+Xz
Lkq2s6ujKvK47sXMN1yyfSX0FtC870noceoZnCoc4M08oCcWVGvlAG9me+r0CG3QO8B72Z7F
LxsVvT3Am1N6PZkymtJ7gjen9GpCycSB/WquN9wh7K5zRyaR3EwyqsC2iutdif1NRtOieBsS
eY0YzLgucu64TOlNRlOLFM65VH+Twa4qS1J6V84dNswhbkUTrK0/UnpFcKL35Up/k7E8lP7Y
WXijhtZvduTzZpfGTPxnY/Ee6HBv3u+Zz6NfXunv1jgBOEiw4A25gBZ/j/5gS6BYwBO6l4jk
Fr5lIFU6wJsJsSVUzefA7qXDmSVlVHHgE731O3Sq5BsLrMIP8NZP6HcE/6PgLN8AL6HEZ7TL
icpw07A7Dgf+E861+e3WqrNJUK+vbZhSnoqGnXap5taddOUKFlJ5CfEqyheUeCoaSjVyn85U
nKeAwcQzK4rc+aLIPaw0bgVTUim1VmVu0k3Ru9cK0U7i0/Gb98loQlnGuPpNvGV6aIJicjQr
KLGcpnI/pqMRv0RS607x+x0t76nF+dkp8d9KejAXcK5vgLeXuyuqQzzAe/leyMyg1soDvJnx
VV+5Cv6oP9Fbv8UYO26oweITu5eRMqfQCsEY6QFewCnoNM32Xz0fnhrxf+7wPY1pAu1USCpY
Uo2HlvC9s4Tu+2Q0Tt1azaQl2guqYlOj/tCSFGg7IxUfk9E8Ru9qTCj31hlt//CHVhA+Pive
f+60t3vROHdjczIRLdJSYWPpFdKn9JBZud5pN6Nx7taycFdzMt4eo0sY41uhSlNO+0Q+psOR
1nPMsGlpJAL3aE79cl6M79sFCEvOyV8r4K9woLf3lKmCd6kB3kz2anBgVIDwCd5M9qympqiN
8UDvJXvSnQWjgjQHeDvdy6hkzgAvSe+dWj70XAaluGMq0FNuWoyc73URwwiSP7SCINXTfsD3
yWj8fsdh1Ed+h8qothYv6Qe8pntT0YSSAUvvvkIKTyvHQysYRT4VpBnRvN2LJiezSsrVuasQ
K9p6mpeYi5wPxk+HI9YrS8slO0EC3/nO91aEw3TaSTsdDpv/cNivFqV3tD776m789VUI/bZb
UcYy0Juby8S3Gewl+wRvbhsoSdBq0gBvXueiiQvYy/qJ3kv7epiwgTpJT+xe0qc9DmSw6nyA
v7am2zMNYnHHXaAlo8bipLQYk2ANTv7QCpp0SfqmonH+1luYMyv5eQyKNUclYAXps9NS23Q0
YTPbpPoZ3xs4QBUPrWhz5FOJmhHN271onL6FnEvWHJ4pFS3qrrAPokfR5Xqn3YwmrOGYxVeG
yCnlZkO5etroOB2OCGUzlSxNcbu/uXTAi/N9swihFLB7Z4D3cqho04INUA7w5s49Sg1VKxjg
ravMvUaFCEx7HOC9XF6cRoAJ3Ad0802j++UBVcI8wCsY3ml2ws9dHizinn+FM6KslQujd3l/
ZEUs9aqGOxVLSZ2DEImUkNlB80Z9BVs1Oku4fkxHU2O4oAlJzhnUMS6LmvZOuffnPnu7F00O
qXWLGqFT4YL2kOQlM0YXjOh9OhxfGr9FmHS1XDJaxF0yyfKwj77ea/fDyWGGp01JO5yilCn2
/eJ3P4MEYU7R3gxOLD/Be4/Y3Py6jsrTHeDNNK8nQduPn9i9JE/ZTwNQ0myA966x3x/UUKHJ
A7yZhsaYKzh3OcBLiN7pxHLPMujEPdOK0P+l8JEzZ0ggdfWHFkTTzq29JqNx1lb99PX/cLEQ
2kCp3oq1sVPZvo/paJoveH0YuDZieP56yVhsO1WnGdG83YvGSZtyyDLn0KhBDQ3yEukg4lNu
9D4djsT93ClrUcroibTKRa5c1G9nw2Enelab5Yev85eK7by43neLEKJmDgO8meSVVNA81ABv
z+VxueEpEuCtqywUFzEs2XFg965x2KwxOnR4gDeTvGhuQ2eDDvACIkGnc55+9NZBJO5YCVD8
hLMIP/qmUGK9ZPa+1NO+//fJaErSzmGOEjMZBaw6xUNLSN6pU/B0NB6M1ZI9loK21aYVClJE
5UzJ5XOjvd0LJjv/zpFkrU7utYE6CvHUknTe6RDudDjSIzEpGtk8AlPH/tQKynpZr50NRwqF
yU8LyYUKe+C96rULON735PModUX1pg/wZqrn/DKDef8B3kz1NExXUcWVJ3gv1dPw1AXT8wO8
9TvkLIkbmC8b4L37UJu/tlHd8wO8guzJRZ98G4Tijp1AmOrW6q93CzE18CK/yFT3oalzdgRP
RUMpeCsJO6toBUyrx0MLotHTbOvHZDQlmS+4+XssPwz+QLa34p1M+epa0QafuGdcoc7ui1Tq
2eMBVb3iqRUZPT6VIZwOp4aeovna5NIq2Ai6SHOF7WL6ZzYc32Ycnbrdfz9g71aeFLz82dke
f4UMIahssqQvZtmcyHfI/WF39AO799wvIXcMujIM8Gb+aamhzGSAt65xyeGni6qXfKK3fot+
6U3WwI7rAd7LkWuLdgqwLn+AVzDQ05SW84I+WM4dp4MWDtqNsuYYQACrsG2JzEippz6s75PR
ODWW1vwAda4eZn0on16RPLWrlq6paCixX08blxqMDVQoj4dW1JRPRVM+d9rbvWhKytY1+hKj
uxNuhixLBG2uxkOmoskPd+mqJpxLRi2u1oyHOO394Va7HQ5rzVmcTVs0OqPpxtdI8DKq912i
f62gjO+B3cv4Qj1NQOo+wHsZXxW/VIKDogO8mfFRj+EPkPA9wZv53mPCBxTUO8B7+V6PNjpU
Y+QAr+B7p4YHfgrr4BR3DA9aajXX3qj3mrmikn9tBUOS0+Hm98loOJUe+Z/aCweNBfleWVNe
PmNIH5PRUJLiNy4pWZuHg2rAzLXw3+F7OijFPQ+X4rTImVcXZgNz2yEMvYTvXXSrTkUTzK2H
XVAv0hk9M/MauSG7mjyfDEdy5E+p1VaLgDel39X35G8g+ZdNU1XUHH2gt5M9WLZkgDeTvZrI
wNLoAG9e5978eEMHlwd667dYi6XMYK/eAG+mezWhjssHdsFb/lL7xQahuOnnETtQqvNIooaS
vSXaL5f6zlPRhDVHzDpY104CNvEv8vOwctHgNRVN8DY/ebk2q7mDWgg06bJwR/DPBp+4Zxph
3ao9CpjZr2doAXNFZYGKng1uv0+H4/vLfzalW7R6glo2s4rI/8H2Li4Wk+GwOMnr7EvEflNC
w5n76bzY3s8j+CfxzoR1np/ovaQvmvBQdfsndi/la34lhQXrD/Bmyqch4AdKZRzgvYSPNErx
4BDTAd5L+EySNPDqMcBfXM8twzai3LP06JWp5cpOJ9GRnbakqf/Kwm0yGk5OJSQa8Mxvo2Ad
gNd4NKucU765aJy9Se+t5lZZOviL9YdWtOBdUb4yXCNuRRPkrfracCcKXzq0ZGgr1G2cZf5o
q90OR5zs5V79FWmscDgr5kec8v1wr90Oh6tvsd5avAZqgynf1GvtRfm+We+vdnB+a4A3N+6V
1A0VrDjAmxv3KDXwfDmwW9eYe4wKoDmPA7yZyPurvYIl0gHe+wkpp9zRXXiAV+T1LsZGyjCL
KPfMIppfNahLFqoZzE74Qyt6j6SfJ1vmoimpqZqfuJmkZnjQoi3gEcXPxvODdzKa6nfo3CT7
sYu6VZY1gwkk50XcMqwibkWT/U2npcdv1V/JFR2zWCP5dyqc8j4djXCY2mYjzgVt2ZuTTflz
MHKuODQbDBubU1XJuViFbYdfLXsrGN53Kf5ZB7vOB3jzEat+v0PFYA7wZqLXE4Ot1Ad2M9EL
x11wgmSANxO9dqMn8wBv34WFwG6wAV5AJsppl7kfv8MgotxR7Se/qzmRz63nGrYKINGrK8pQ
cmGjNRdNSCu2rF2p55bRXpQlonLFTkdQP6ajqaIcTZTO8lDBXX9oRTaPTnOTnzvt7V40wdlq
uM+RUljFoGrISxT/il1k8ybDEclUqHZhEeavtbv4Uzhyofg3HU5urbEvTfWowOm9l7rzL6r4
1wws3Azw5mweJYUzPQd4ezYPFS09sHtJnoqf0aBMzQBvJnk1aUHV5w7wZpInyRraN3WAV2Tz
TitPfvQOl4hyz7+jZ2GNWU8j9JcfDy2I5srBYy6akjpp1J89oALeBBcZeHS+yLFMBlOVcilO
jXptaBfIErs5Ku2HG+3tXjTB1nrJIWkjlUGN6rwk0UqZLm4Tk9EImzNHbaI5Kzi6vobiXU5k
TIeTi6+LdLFqGZZjfE1krKB435PO4xjwB7N5D+zeE5ZrODqi8xhP8Gaep0kZFCQc4K1rLFn8
/QlWgQZ47yr7FYI7KqZ3gLdXlguu7fwEr2B6ej6PUYZJRLln4OHfnXWi5jSyZywp4Q+tiKad
kqP3yWhC2Ziakz0uxgK2/K+RQy56yls/pqPxRanVd7hQJ3hctS0Zvs0XbaDDIuJWNDl2GlPm
Jk6NKpzOW7HVLg08ZsORlv0+YblJNymwV9saA4+L5rzZcOKHU6rE/xRs0P9dDTy+RO4PdcIs
S3qFl82J7Bb8q6k3MFE2wNt7tjoornRgNzNQS2HUAAv+BXjrGoegRDJUq+4TvfVbFJUkFdXE
fmC3fj6uUewDGegAL3itXI6HDAeLcsdWIOT+QlFOKMQfFGOg8dCKXOOF3N9cNCH3F8olpfTo
tcNYQTy0goHqRbJxKhpKXClc5DI93I9Rub8lfhx67hZchoHFrWhC7q9x94iyFoKdX75c7m8u
mpB/Yc6le1A5BLQ3yv05Ab3oXZgMh7t1LmRhvZhhf7+5s+tnJ6B/K7k/UrCMMcCbc46WDMyL
PKB72V6NyU+0DHSAN7M9otR7h9X+nui9bM+qU0zsEx7YvWyvEa7yM8Ar2N6F2F8ZFhbljq1A
S41CYqRaya0LLPa3ZE7kQuxvLhonbiFMFVXlLhmsk8dDK0rLF2J/c9E4cZMaUoy5NM5odnsN
27sS+yvDwOJWNEHcoqfTDwyuDRytWMT2mM9uSe+T0YRsH3dqzcKaB9X9XCP2R/n0mvQxHQ6r
aetUIsVtsDXea1JkFdvbLvZnqRBooPCJ3l5cJn9lwMXlAG8nexWUSjqwm1e5h+0rmuce6K3f
YS2cCoNUaoA3k72ahMFumwFeUVy+EPsrwy2i3HPyMMni61yd6xVQvyIeWkH2rpRfpqIJdU8j
js4uM387oWJ/S+wV+Nzfay4a520tXPHMGZ8w6mA0KcZxR/llmEXciiYGC1tRc+7aczMwi7xM
7O/cOXg2HGlNnbxG42rz68VGsb/nEXi9126H428o6c0qm68PKGoVT73Y3iK2901if5xyA3fv
J3pzrxk5TQIZywDvJX2tJFS99MBuJn1KCc3XD/BeykeSUD51YPcSvq6pP7xvoQHrJ/ira7nD
LqLcs/Lwt3vv2TpVJVBOzh9akQ+7JHxT0YQLW8nUSiUTEyyaRdZtl9m9qWgiu6fCzo4sk4CV
6VXZvSvCN9wibkUT1C1byc8WPCdKOwnfQxHoeqvdDse3LwtV9gUinL+ukKqgLBfF3Mlw2C+l
vVCv/uvhDHu3vdSd//rkyH6pv46OZQ7wXooXSZwM+k8M8OaWPUoN7TYb4K2rHAZiHbQ0P7Db
i/RdQBGCAd68C9WXDR0OPsArsnpXUn/DJqLcs4lo/l/tmSU64AmW+ltC8q5SLVPRhJhL7kJF
LEdD1U4FmC4XqhyT0VQO6WPV4rQINE4va6qEl1J/wyTiVjQh9edEWHJzatRxebxFWn8X3QKT
4Qg5ZbXmdwrRBspKLlP7u6jhTobDFq8X9ctE6QbKDb1quL+y2l9JGbVDG+DNPMD/qIC5ngHe
zPW6X3PQbrgDvJnraYLV/gK6d4VFEywCo0vG7W5KwLQK6/w9wQuYxJXOHw1nCLrnDFFbq9or
s9UMjhOt0vm7EHSeiyYIWwtRN9Ma3gM7BZ2tnAs6z0ZTSVp3GhFeF6BVUVnT+U/yw532di+a
4GuSrZJ17rWAnoCrWF49zxrPhiNC2h+TGRKdrj+LCMx0ODnicJLXq7YOZyZfIjB/neVt1vlr
2RkbmCgb4O2pPBUDj9cDvD2VVzrqx3uAt9M7AQsMB3YzwfMvJYO+IgO8meT5vQHUKjuwKxJ5
p5aifvAOXwi66dnRKJq/slm05qCJvBW154c4y9m5OxVNSU6INNw6jGsWVC1liWah2nl73mw0
tUqrUrqaoW6UG6ScaRhD3IrmIeWsTiLYLyqZCe1nWyLlfGXaMRuOMDFRVnX+yDgn+mrbjtlw
2KRZ7+YrX4vA1dpXIm8Bxfs+nT8wTTHAmxN5PQmBQ+0DvJnpRS0bZnpP8F6mZyUa8FEL2Sd4
e/clqjV1YDfvQkqEtl8P8BKud3ECD2sIumfb0dgJhSqLGqGOc2mFTco115uKJmhbzjFx64xP
cEnnFVyvn5Y5P6ajqY/ZBV+bbhkcLImHlnC986EfGsYQt6IJdebatJP/K1eG03krFse53rmk
5Gw4vr96i5l1/3fBdf6WaODQxb1iNpxCZLWEGrq/79HB21/TtmMfk/ufP/79x//98e///tc/
ir+Z8j/++b//2npSYa/A3ZML4NDCgrfyAir+HXKHjSRRBY/jAd6c7IouHJSjHeC926yWRB0d
QDnAe69bmVNHrZIHeOt3yA9lJfCm8MRu/XwW4/boBxzgBa8VOjXjdXo0/DvojqlCDASbdY2W
tpjtRKeIV7iR1HJBxKeiifqF0zw2KqYMZo5oSc9I6afXio/JaJp/MBKrvTTSDHa2tiXRUD6V
jPncaW/3oslJc7MYX8qNcgMPGX9qhX441bNb0vt0OJW6qN8scufOBa2rr1HA4fOZ6LlwShLT
mCyzVk1hqfr6KquvInrfkXhtnBNXcE5hgDeXXzlZA4dRB3gz32upCTpVfoA3873wJAHZXkD3
rrBSElB578Duvcr24mcQeHkc4K/mesPAg+6YKjwGiJXID6vSGeyhXDRALP0iEzYVjX/RmYuw
n1j+g0I7mP2hFQX2i3HouWhqqs3/Ib9uxbwfeDdb0t96zfWGfcetaILrOdvzneZ0r6HhLOJ6
l0nXyXBENHcKgUBxDgsX2JckXS98uefCKYmVM/sCacnoGFN5SVsv43p7665WgqeDTS4DvL3H
TloDq4AHeDPJc2ZZQD/iAd7cQxFHCEjlB3hvUo85sRRQSPAA703r9YeNFvYdDvAKqtcvqp7D
KYPu+X60LrWrxLgM2q/HS2YYnFyeD0XPRUOptNojLyHi/Ah1BSwronnMs5wdv1PRtMS5RgbM
GUVuYMnTH1qSB5OLS8UwyrgVTU7RtOt0r/XGhRQel1nio9d/uNVuh8O+1WL0vrbGrcFK0Gum
fy56KafCKcn3WVNqLZfoTgGp3lzf1Yvq/SRKh1Z6YsYy0gd2c5+dJH8ToSqHT/DmXoGc/KRB
ZQ6f4L18r1NS2Bz7AO/le36VoAK6zg/wXr5H8Uc7yPcO8Aq+Z2dXej+Fh1cG3XP+qN2qFFPz
jQgyWH9oRTTtVK/tfTKaaP2VXnqOqVUDhbrLGqHufjqB+zEZTQ3PTX+BdZZm6MRqOIku4Xtn
jOJzp73diyaYm0g1dhLrtx+4Y28J38unNtDv0+H4DYla5tpFVMB3waw0IKxD+TEZTgk127CX
Nn8fKFiUjodefO+v8r3NQofSJXUFm7gGeC/LK+KXKfAsGuC9LE8khQQ0ODPzBG9dZbLwJAE5
1ADvXeUcBmKokOAB3voJpdTU0ALuAC9gEg+D9bOzd5hk0D2TjMykWnOhruh8dF7TqnfuFzsX
S0lSgt3RY9AEniiea/z/M8fjC1mSyZVRlUzShGqIc4Nrs+JWS1QvbhPDIONWNM7WnHx7NOzM
lQ1u1VvD8S6EDmfDEdJczFowcNCwatV49I+32u1oQgXLl6VSdSYONx7O7bUXx/t+nUPRHNU6
8AA7wHtJAPdU0JmHAd5M9TQZ+BUe2M1ET1Oc6yDRe4L3foMavrcgnR/gvQlHa/61oLbEB3gB
nWC9SLIMcwy6Z46RM0vpVYqzJFCZlyav8f+RzruoqU1FUxLFWUVU/NwqoHFJWdN3aKe9bR/T
a9P8gmCNnEVSRRtXl8gUXZdvhzXGrWiCtJUStojMvfm9YivVOxVvfJ8Oh1WZqUYSPDoPv1Q7
5g7XmwxHnd13v1q0h5cgGs6cRtqL632j2qH0mjqczntgN2fzahIDBwQHeDPF49RRobUndi/F
U/MzDZxkeWL3Z/IIXeEDvD2TZ9gJ9YSuIHdXtdphikH3DEucupOfTlHjVDQ/7g+tyOO1Cynr
qWgiJfcwIaauFe3p2JHHm1wbNY+m5lysMFh5joeW5PHOrXFoWGLcisZpWu7mm8w3m3EBuWpe
4o1zncebDEeoRyq6Ze1Wda9hyY/32u1wtAvnh6I9E8Ph6NRr7UXuvl/nUJRTFrCaN8B7OYBk
Z5aoYcQB3svyakwhMzpu+wRvTuW11DqqFXmAN6fyasoNrXsf4M2pPL9AoN0NA7yiM6+dsz0e
5hh8zxzDOpdWVbuyGKqmt4S71ouh29loiLOqZmd7ueGpvBU1aONze7q5aEKFMrNKSEJ2Q+0a
/aElbO986JaHNcataIK3SRRWKFp9FNSLWcP2yqO2cr3VbofDyoXCya0X50eo297cmCo8Ev0x
HY4W7WFC/HAuAa8WkQD8Hdkew2zvxqEBDpAuEZFdNiCyX+AvV7BENsB7GSi1JBllTwd4OwMV
AeUzBnjvPYM4+b0fvGcc4K3fYfOvpSioBT7AWz+h1h4JTuw7HOAVXYMXHfs8vDv4nq+KlmYa
jsJ+WQM77Wjy4PlzMZnPi8lz0UhiKr1m5wS1VpCBxkMr8o31PAc0F01Nzbqp/wZzWC/CsyEr
xKkf1lrXO+3tXjThq2LZiXRhbcwwZVvjq3I6PPs+GU7YsZb/BwAA///sXVuSI7eu3BEDIF7k
Bjriqve/nwtIxf44jqpB0Wx229aE7TgfyTOCWCom8chs0ru/fPz+lh6mWDEacqX6MhsNGfmu
sHS2bEs5Tg42/3b++d9S+KvJhuQB3kv4JCTGklq6A7yZ8MkdhT/5AYU/hFJ7crx/gPeWbtVP
LUoWlwd47y4DSemY/Ihf6BVJxwulPxoWHnTHVsF/JNbU7x0G3cByuQZftCIaPhVMeUxGU0vv
NUKpzCxJB9tYtILy9XOlv7lotKiI9Qo9GgCShQxd0z94pfRHw8DjVjSh9NdDuLD506Y9edCs
UvrTc7fk2XCMIlMfBsNkLZmG8FVLxoGvEtxT4aAfRU74CFo3lbQJ5dxF9s35fl7pL8Z8ktm9
Ad5cX/ZTk5J5nwHeTvaAk2W6F3Yv1VPyAyT5Yhrgrd+gX5hLzZqqDvBmqqe1SJrpvcAriF47
o0Z+/A6LCLpn3xE+emJVoTIlq8u0xkdPLsQ4ZqNx0tqZqh/CgJxVLVxirdLpguhNRaOlyXOo
QgG1Qu4XG4uWVJfPqMTXk/ZxL5qoEzdnwyH94rwoycJX6fxd9BJOhyPWRLiBcYV0890aGn5h
FTMXDhZUDatxJ62c/eXgpELmm+j9Jp2/5NTtgd2c2mvFIJmWGuC9TEBDACrr2HqA9/I9qwVr
Ml0/wJtTe3E2ZMfTD/BmvtejCJpteBzoFYzvYnqEhlEE3TPxcC5K0eal0gCyjG+FUQRyO2MV
j8lo/Is2Z8UIziks2bBQJzvg/5LZOxf6mwvGuRtKE/8XRC1ZaNclhfZLoT8aLhG3ognqRgaE
4uRVsj1Diwgf9oti7mQ4fl9B5mdx2v9XdpR2zuHsDuGbCse5W4+RbQDusU9ZwjeVE38Tvh8W
+tOWHRo5wHtpHna/tSZP1wHeSwCYSraX68Bu3eMoa0tLXtsGeOs3SNhKvGqSYs4v8N5PGHMq
kHSGHuAFPIL6+dgmDYMIuifab/5eF+ehzK32rPyxLRkZ6RdJvaloaqmh28tir/8mOd6KpDW2
0wLh53Q02oyUneepQlbxquiSAWG4SB8Pe4hb0YQdLVfU6KU0hOQhs8jEluyPj9rtcDQeMmwx
MGKN0km973XR+5wOpyGCtm5U/YqU1uaZq62/Sd7vUPqzrB/vAG8u4HJpmh4QfoE3c70W06Bp
pT9ekU24NR5shVr2GzzA29O2mu3eHuC9KUenwK0lT98BXsL1LvqnhjkE3RHsD9G+auZUApx6
ZS0QFyn94UX71FQ0TkI5NJ1b4ygRZvuNVnRP+V97MZwxFQ2VyONBDIUD16TwEE2aZ90p4A5r
iFvRPAu4YuKR9JB1znK9NQXcqzmgyXCErGs4AlprPR3OityIc72LZoHJcPyyF2164o8bi2ap
61yz/pvr/bjSXzKfPsB7CUDFApasig7wZpJXi7W0nvMLvDmlFwq2Sen8Ad6c0rOn2lkypfcC
b0/pMSVLnC/sEpJ3cfQOdwi653Xh97QQ12Xu8BRlydGiFelJ5Yssy1Q0kZtTgh5mcy07dFTX
aMDYKQH/nI5GeyewaEKVnpbaXjKB+2zruH7SPu5F4/ymNugVY+K7Y3JmbVFCr/JZOI/pcFRb
FKB7q6QtOR+9I6E3GU5DwNibXtksaUn0Tuj9sxX/0JKivwO8OaGnRSTJpAZ4M9eLirFkXdpe
4M0pPXFylKxsvbCb99iKX/qze/wCb07oQYFkpfPALmATeNqW4+fvMIege1YX3dgfP/PDyilF
2rl2SXeeXRy/k9GocEduZq22pHNtLPrudN5UNBSmKgIKgmicjIaWpFpf8xLXT9rHvWginVcZ
QGJUlXty3GqRtjO2c8vn2XAEqar0xiz+tKWJ65I54qt03mQ4nVCqmpifl2bZ0m3/Vxp3fIva
HyZvnrhE1WDZoMgP6P3lTqEXdHPjoBXDpJHpC7udeXZNHnsv7NbdpWqFOSmS/MJu/f60U/H7
e1Li4gDv/YTg79ya9FUa4BU5Rj5jN84HhnMF3XOuwEbcpPr1rPvSZB4Ll0i+nI5SPCaj4aI1
5lxUm1JLNnXyEmVmtNMp7c/paAAs3Eq0S6SyktGseBvXp+PQ9ZP2cS+ayDE6fW7URKFa2k93
xaW84ilVe0yGgyUyctFtK+TXg+yVDZfwaDgri39Ob44fQgA9lD1ibidNPKfu+7+deP6nZP4w
q+06wHu5HlHpkh3xO8B72V62X0n2+sYxtkItWSwY4L0sSuUpNJV7+g7w1k/oFMLv1smnb4BX
8LxTjZT/Mx6eFXzTsyLU8DRGi6kmmdGaeiUKnKd95qLhUnuo4Ak7nUjqFMaaFTTvVP74czIY
KUEgkiKcZcUvwNnd+T2Ch0/FrSCi5Erdf6B+k3B6l7z9rhJGudBwngsHo4cz5nVYuSpk52SX
9HDCn5+w29EQ+tnoRBVC2TObkKd3/XgRudut5+dPYrbNfYC3s7qmyWH6Ad7M6rgYJtnTAO/l
d2CFkrfoA7v1G/SDstTk8NmB3fv5gIoI5bIqA7yC27Xzmh4PNwi+59Sh4V3P1MEkO++3xo8M
lc+1Xeai4dIBuh/pIUPNNevU0Vcw1Wer2NnROxmNsAlyRSerlMxp+6IVan6A5+IuPMwgbkUT
pkTmF9nunKgJptVQVlimX1jpPqbDaX4Xqs1vv8CQ7xNsa5yBz/sEZ8MxqxVfI+aYLPDApADA
m+b9JjW/pCjtgd3L9cLKLJ3BO8B7uZ6GX2K2U/AAb91jf9WGSFhSze8Ab8/lYdbdboD37jJU
CX+LrJrfgV7SL3hxDg8zCL5n1OFUhalG3VazUi+0pmor9bxqOxcNFydHoZyoIerHOf7qi5aM
/7bzUtpcNFrIoiyIlbV1TnbRrPGfrRfebDysIG5FAyVcR9Aqhij1c44mV7VdMs18lTieDMf8
iHGC1Pyy5G+gbJ3Tlgy6wNl74HMynKgnmxL4/zVpl2RnW8F/pTnwv17OLywf03J+Ad7clQcl
64X+hG7uyaulS3KiZoC37rC/HdJdeQd26zdINc7prJTfAd77BHYqJMmc7QCvyOidmn35qTs8
IPieLj+rQOOq1J+SHqnXOq8YB9GLacy5YGpxYsehoRsSL0npaV+0IppO50p+s9GAVGDt1XdG
s2pHvmhJZfAidTwMIG5FEwk96BztqVUZkroDsWpFG5te5I4nw1G/F9WG1kGgt3QVeg35vkge
z4bj9A6aRHpSe/J0ndXeefO736Hk17M9Wy/s3iO2ml9vkxWmF3YzzTNnvklX4AHeS/NChrln
B6cP8GaiZ8U0V3c7sHs/n1mp6fmVA7yE5l2cvsP5ge+p8RuSSVNE4JpMFcWiFWm8U4uRx2Q0
TtmQQyPOWkdJdhnFohWF29Mh5s/paIRjGLMjx3RpluctKdxeCbzw8H24FU2MUTzlgFs8bWki
sUTfBfVcSmg2mpB3Ed8Z6YZS04LNK2jeZd12Mhxr/oryh8x/O5aneXMjZW+a98Mifn6tT7aB
HODNaTy/rPZknn+At6fyOOuxPcCbU3mt+PspmQw9wNuTeRWStusDvD2Z1zA5mjTAC5hE5QuW
N7wf+J4vByv0Gg61Grf4bDZvjYzfRbF2KppIzAmTOS+iXPOpr1hRd+50Pl87Gwqov8H83K3k
/yRfeYua/E+r6F+P2ce9aKD4rjCrf08eFCd/28tSeRccbzIc53hRcjbQGOnO/WyWpfLOLkef
8+GgcczWEnRp+L0+yG+O9zs0/DjZIXtg9x6wMVYhyY7kAd5M9HohTas1v8B7iZ4+1cGSRO8A
byZ64F9LUvNogLd+Qgb0Ww4kc94HeEk671zhgofxA9+0sVAwacLmdC850blIr5lPde8ek9HU
gsymElO2mr2y1jVdeU0uciyT0WiH6pSVojM+2S69yIANTh3Lvp60j3vRhB8FgwD3l59zOp+3
ZHgYLu4Uk+E4MTIg7q35DuU9g5cw8dOxks/pcBo5A29GtYenc3Z35sZKfjvXq9+h4pe8rK0Y
2Ls1SJAcIVjwilzAi39MWZCSL6wB3lziDiH4ZGrjhd37kAkWguR5PMBb9xhDdFGzbn9f6L28
mEK8KnnSDPDWT+h/YdiiJQe7DvASXnyhDTK8MviOf0G4Olt7Klxrx+RtqS1pmUOBi3bGqWhC
/NBDCa9lBW5ZJrlCg/R6WmUqGi1+DwLT3v3Wku3u1cIr1K3BLm5gwynjVjRYumDtGCrqWikr
27JCGSFSyH960m5GE/V3Z6egqFQrcrabcUnVHurFsMrk5ojAc5aI4lWVPMAmOyp+Oyv+b0kM
clJwbID3Ej4OodWkDN0Ab6Z8Gtp3ST51gDdTvtpL0+wM9UDv3ecmhTDroHyAt37C1qWAZeUG
D/CKmjdcHMTDNIPvGBlYVAvIwpxUNTuSE4uW1LzPonlMRoOl+fHLTviqIHK2gr9keNxOZz4+
J6ORYsgYDaBh5ZwLRpY0nV4zvuGYcXNrnPFZlYoxZJTOuS9hfNgucu5T0YT4RbX2JH3q5C87
nrxIX+ficjG5OVyBnRgr+amU7EiIRW/Gt4bx7dcdlKxD8QBvpnq1ZFu5n9DNNI+KX6myNO8F
3kvziDXE5pJ57oHenNnTAllj9wHeu88Qee2s8PUXeklu70IfZHhU8B3jgFZMmkmkCwie0jCp
3N6amvfV+TsVTeT2FJDQD62k2tKqzN7pDPnnZCz+09NQOkHTaAPN6tAsqqle8LxhUHErmphu
d5qn4famnJQ99UUrugHR/vic3Ywm2myaE6Lq10zh9MAHrfAnvlShmdybUJe2MCmv2JOpnrcK
zb9Ad5AVc2xlgPeyPeFSNTkoMsCbGV/kwZJ8L6Cb2Z5ICYeFJNs70HvZHoofwEnOPMB767jW
SoMkmxjgJVzvXHVQhlGF3LERaH4Gd3Sex9Sd2+e+87bkDEY9db57TEYT9slokUHlaprtp1jj
uWx6zvbmolE/TmvrWK07sWi5rJ5OnsE32J4Mw4qbe+Nsj2sHbFVQs3XcJWwP+Hwwfi4aJ27s
L0eyGPMPipSleyu6Nc+9UT6nNwfCX7H2/gwnmw2Ht8z036Z7PyA62Hry6BrgvRQPuRAmj/8B
3kvxmOPVnDxeDvDWXRaJV02y9WeA9+4yUMlKzx7YrZ+PKQb1ksXvAV5Rtz1Vt/ODd9hVyB0L
gRijblGvad06JDWA1hQ6n33yZ+fuVDBOCJAhJi45bcftS5Zk885nCuZiqaU3J98ETofa00Im
lZvsK+ZXKp0J2309Zh93dwaltSadxGrWxMgXLclN4sVNYioaKE5Vw7OxNW4hxJyt2q6xEbm4
SkyG0yF0aEDAPKpkw0xo0b0J3t8neD+lOig9udEDvJcBkBVskKQAB3gzz+sFqmZ53gu8l+cx
FU56RRzYvd9gs2JJM9cDu5flgRTOTvMN8AqW1y7SK8OiQu7ZhyhrZ2aKnrbsLF3RJQMZV8fv
VDRYqvQeR2+DEMtNkokVXcZRWz0/faeiqcUqGLBgZ83KcMaiby0Nfj1pH3f3xhlE01YbA7Zk
WjIWLUnk/fFJuxmNX307PE0JFfyGlGZGtGSK/GJOeTacFn0OZNactHJWkqZNHVtvnvejsoNa
ICmhdGA3p/H8tFTOuoe8wJvpHYXDebIUeoD30jsSP6GTOioDvD2N13oyTTbAeylebSVaWHI/
lAO8guLhRYZl2FTIHesAckbQBKBxGFMnK2i0xOfqOpM3FU2k5XqVyn4ncXaUllBcsTdPrbaz
c3cqmsjlOY2g8NFtNetXs8Qx6ZriDZOKm3uDvjPVN4gaKqRzeUso3tVlYiqayOU1QkU1snAG
/jW5vMlwWkx2+3VPjMCSo0sw6ab95ni/Q3awUjJTNsB7aQBDseyo6ABvbsvzO5uk521f4M25
PC6KyTmMAd6czdMiLZvNe2I3Z/N821py1naAvzubN5wq5I59gN81arjY+wFMnAyIJoVl/9KV
d8H0poLB4r/4LlF3UtHkdGosWhBNv3B2mIumhrBdt9ZB1ABzv4a6ZgbjkukNn4qbe4PVoFqN
cmd61n8R04M/Pmk3o4lftCLGgCr3p+jRL8nlTUbT/L6n7ExcNWQu/9Oag/QdmoPJ2t6Kqt4/
V92PSjfLqvu9wHvJZw3Fq+Ro3wu7nXqyJbN4A7x1j1uvUXpNqrgd4K3foUoo3ebegAd26+dr
LcYIkspxA7zgpUKnwr3OCIaDhtxxNZDinBO7OXlnv2Xkcj+xaAX3PJWreExGw4UqUeuMXXpW
sioWrSgk27l57OzeOL0Jn+JGIVWY3JoVI2YXSiJfD9rHvWCwMMWoju8NhJZINgG8hHqeTlA8
pqMBrmLUBYSTehmx5lu35nN+a9DvndZCeVGSnkCzfba/nXj+t2T9kvmnA7uX5wmVmnxPHNjN
PE9C9DjL817grTvsN+NaJDt7d4D3pvBUS5Z0HNi9ewwWA0dJoveFXlJPPneckOGfIXc8DayE
yJoRohi35HNra+rJrOeCfnPRxGBEZEm6VfM/2QZIWKB6jHbqO/M5GY2WDsjQpBI0S9aTdbLG
979ZxlNy9PWkfdyLxq87EK6n4tcVs2QiCyenD/6XHenF7O9UNFCModYeIlPwopKpvNyKWoO/
BS5aFyY3x4Bb735JUt/6bArY3uXkRWRvv6JfzUpXvLCbS8lSumSVug7wdp4HkrwUvbB7WV54
W6hmOcpAb/0OpfeSbU8+sHv3GEFKs6xR4UCv4Hl2kdEbfhByz6tDGnbkBuxncHJsPRat6BuE
cweFuWioNO2Veo8uyOx7whet0HhpeMHzpqIxv0VXNKUnOYJcNdnW1F8Rz1rTvp60j3vRPG2x
q2KohErWK2iJJGulq7bBqWD8rSiNrHY1iqxrkuWtEVts52bFs1tTkcT8jmTNn7VsgrK+U3qr
WN5PCfppVpV2gDcn9VrR7Dk7wHupgEYDcbI4OsC7CR+F+kJyUHmgNyf2/GXSk20EA7yZ8hEW
yHaIHuAVqTA4e9f7MTzcIOSORn8rhECRdzTxkysr6kcrZFK4nRU9H5PRVOdu4uTIORIZJLv3
fdEK+tqvmrqmojG/DgIphZ+0WdKT0pYY5znhu7haDDeIW9FgmFs0UPWfQ4iFZhnfGnO2M/r6
mIwGil9XtDcn4039IpZkfLLEOO+K8U3uTaUq5K9RRalJydxY9GZ8f3tMZL+mn/asisUB3svy
MJSOs5J+T+zes5+pVMas0ssLvHePkQvUpDT3AG/9Dgm1RKtyUrb5Bd77CTsXkWST+wCvSOmd
sgg/d4cRhNwztWgdyKhZJWmYK6jFohUpvX5RUJuMpkI3ZIHeEZMJyjqZm7ij9jIZjQmH1rHT
IsO05cgKy/GLIYSvJ+3jXjTg7Nvvs0AgDCbJCxwsybfWyhcUbzIc9V1prfvPR7El5SnCEf5b
d+dzfneceMcYsG8SP5/l//CIyH9G1y9L9V7YzeVb9qcraX8zwJu5XnPqkUyAv7Bbd1iIng0m
SdGXF3hzztb8/Z4UzhngzdnGVjCb+RrgFUzvYhJYhwmE3lHmpxKKug26H8KSLOnHmgXB6KmC
zWMyGCxG6vc7DwY6pl2llgxpt3o+CTy7NaF8SM7AVf1NliPhsWhFKu9UVuTrQfu4uzeIoMzs
P1YPKNujhyt69Ohi7mcuGj/4SNXvwMBO8S15p4i5sRWbA+d3itlwuj27QUMsCVuyuxUmnW3e
PO9Hdf2ilSht0PEC7z3+KxaArNjLAd5M8WppnFUzOMCb03l+SFPyPB/gzek8KVqThfkB3pzO
kwLJnO2B/eZkng4fCL3nA9G6ADozIqSsoG5d0ut/mcybjaZCl45BWBsnZ402JPNmozEVqj0k
A7FLNhr73nTR15P2cS8aiN5JcJan2nx3koOdq5J5ct6hNxuO89SqTreotgr5ZN6agejzZN70
7hCAhQ1bq35NeifzdpK8nxL2k1az2bwXeHM6T4tIcjZwgDdzvR7FsCzXe4E3J/TMuUdysGqA
N++yFW0tK9/4Am9O6InzCsm2D77AK9jeKT/yM3iYQeg9ow7/EZuAGDH2tLbfkmieUoJnR/BU
NFhU/GfP1UCwJusSuMZ2pJ9ORH9O7w0CKVNTI4SWVdjGFQ1glxm94QVxc29iLgk8JMHWs93B
izJ6p9o3j8looPgDhp2cG0Hz23A6o7cinMuM3mQ4XbF7MMSNa5bqzd2wfzvV+xZpP0zSKlzB
qP654n5hTps8+Ad4c+fgk20kOwef2O3003/G2XLyC7yXfiqVmuQZB3brN6g9pjM5qcR5gPd+
QvBbQ4OkBOYBXkE+LyxEdNhU6E0LEYk8Fvih0yzZTeqLVgw2cz+bPnhMRsNhutysCjRkSk6G
+KIVAjbPbuYzRjAZDah06N33ptek550vWpNqvCCfw6XiVjThN1E5xHiEuj9w3+tSkebSj8lw
ghajeTzdf0CWHm1ewqUvyefs5pihVcKG/h/Icum5Tq3fTj//UwJ/0JJcZYD3sj2iMFLKegK/
wHv5Xgi6tKwn8AHeustNsVjWyHKA9/KpEO7DpH7tAG/9hM6OCiQztgd2Bd+7sHfQYVahdywE
JPLxzfzUqtEPlRQMXqGbiXI61vyYDIZjJhyqB9MrZyWsuNAShb+L8czZrWFtYYpCQsiS9PAu
vIbunTlvfD1oH/eiwUJqRk4nmDlt5kdLgrnQcp4NBpzjscQQMGWZuC9aU1Y+25rP+a1h6c1f
U74xnOR6vmgqRf/mer9C349ypYsDu53itayn1QBvpnhcNKnMcGC37rB1KuH/mJOOOMBbv0GT
VrglSzQDvPcT1mATyQ7RAV7AI54aGWcn7/CE0HueEM4hGJ1vNQDQrF/HCgU5VL6o8k1FwyXm
mp20oqr/tpL1/jW9kP1Uq/BzOhptVbvvDDl1TQ4hxKLv7h4crhC3ook+QIhOaRKVisnW4EXd
g+fhPObDCUWhWiXS9U/rmW9st/tLOH981m6HY5E59phQ1GrSgiRWvXneIp73Uwp/3JKsfoD3
Er4w08026A3wXsKn/quG5LToAG/d5afAMGtWoGagN2f1pBjm+MeB3bvLEJPIlCzjfqFX5PXq
xVE87CH0nj1EMxanFc6WkDCXb9E1Ishy6kDwmIyGnY327t94ZavJTJivWTHNY/2sUvg5vTVi
jSzk/dIWtLqkvfNCQ+7rOfu4FwyWGKtoMZegiMmJhFi0IJp6lUCeigbC8EY6MNVKKJYV+Fvh
eON/47kb4Ozm+G+xG4WDD0BWqn5y/vxN+H5Y4E8wSaEGeHObXnQHJPu/B3hzo144RKXnRF7g
rbtcO4TbSvI7PMBbv0OKRJgmLQIHeO9z2K2gJkWcB3hFc9tpj44fvcMZQu8I9tcCtbdeu5j2
ZCna16xJ6120T00GU6M8SEDEUpOpa1+0gq/2q4ra7NZYq6AmrYbCbnZvVnC8epVAHs4Qt6KB
4tROO3G4JNe8togu6W27EHGeDqcRKTc1BZbkqwDWJF2p/vFZux9O1ep3rnCaI01eKGCyyfXN
8n6Hwl+rScvHAd57yFYrDFll0wO8mew1PwrTZO8F3rvLIKXW7Oj3Ad5M9qS01pMDqgd47yds
UoRzx++BXcAnkC+69IYnhN5zuPBLPJPTI5Nqye6pukYWT09zk4/paCqggKJ1ZE6avdYlOaMY
Dz0/fyejCRZRnR4pUEv2gsWi7y7hDk+IW9H4YcH+hPmuV7Gq+RLuElk8OSNHj+lwNLyen216
ULOCX4u43mUJd3Z3AJuwmEg066Ur0m8r3r/P9far/HXJdoQc4M0ZvVqQkiOCA7w9oydpzYkD
vDej13rpmFQtGeD9Gb20JcYB3p7R0yyLeGFXkLzTi7wfvcMWQu/ZQgBxyEw3acZZRaVVCb2L
ku1kNKFhw1axY+vJrkNftKKcbu0iyTK7N60xgF+kVTHpwuuLFlwnatWLou0whbgVjfObUNd2
mte5sybzk8sSeueGz9PhNI/Gf9e+M8x5I95vT+jNhlOFGnUNFy6sWQ3Gd0JvBcn7MZU/y51g
B3bvCRtDFpZsIRzgzUyvF+rJqbIXdu8OE99Qcz7Ae3keWqGaHP0e4K2f0LlR3Oazitgv8Irm
vIskiw1fCLsj1h/SzE2sQzAKSIrs+qIVCsjSz50UZqPByk5dnVsztmxlvay4C17qOc9GY+J/
evVgpCW5RF0igHMpsmLDFuJWNFBabxq8FYkpO3e7SGQFLiT+ZsNRUWeQ/nZ0oodJJfQNes7T
uyNIVYBCzdmS7six6t/I9Oo/XuTv1kRBcpZgwUtyAS/+KenB2pKZpwHeXOYGPy2y2oMHeO9j
JjGnn+zHG+DNGVDFsNxMXi4Gei83pl64Z73VDvDWT9gpVOuS89QDvKSr8SyZ44xl+GnYHY8D
bE4+DMUaWOfsQEFbQ471tHL/mAynlsoEjYxFsaa7NFeUcpwcn4+uzEWjxVkKdtNWzSx5tPqi
JX2Np1T/61H7uBeN37Ib+U3MvyfLOuPyokEcO0+CzgUTznTUKgAp+NsneZFf5GcHdOZq+TkZ
Dvo71JAobGi4p40g5V3oXsX1fkp/MHT10/qDAd5L+ZhD+ynJVg7wZsqnRZL2ygd2L+HzV22h
rN70F3ov4YNaQs01R/gO8NZPqAIFKFcyOLArUqGnk71+Bg9DDbtlQWFORan66c4hGZJrXn8u
WkH35HyAdDKc0p3kCYuzvkpJx19ftERw+jTd9jkZDRcU6Krop7BAsj61xr64nlaJv560j7vB
UIPWG8bcsCSvSrFoRZHY/vig3YwGClsnZN8d/9nUZFXEVy1hr6eCip+T4aC/oLC2ruwxIWZ/
N3O9L2+69xskCIGTd5QB3szzamHONuYd4M08j4o+RxdTRO8F3sv0ulqxlnw3faH3Mj2Rglkf
rxd2b2Kv9jDpSib2DvCSxN65s4gN9wq7ZZDQC0E3DgtjTU9e+aIlVW88nyKdC6eWp6gGg9Mu
TgqF1DXBdD6Xmp4LRkuMsAA7I9Ym6bwerGF6f3zSPu5FQ6XGgASKxXy85siEL1pSJObzaam5
aMApaG9Owqk1vyQle09DJG1JYu/swvc5GQ6GeWmr/pAZkGWPrzI3fPlmer9IhLBmyx8DvJfw
CZdKlMxKHeDNhK+XRsl6+ABvJnwAeQmdL/RewsdWoCfPhBd26+ezGla+uc93YJfQvYvOs+Fe
YbdMBVrBKIP7tb5rTfY4xqIVxr9yavz7mAynFrSQze0qANSzLZu4Qp+m1YvE3lQ0XCT8mJ1U
+P5o8voTTclL+N4fH7WPe9FQiSF1C1Fj5aToRKxZkti7uFdMBePEzRojawhOx+5k6d53TyzP
hmOtNevRdwy1YjZP+Rad/vt87wc0CA2z/fkHeC/HQy6U7CU4sHsZXtSLe3Lyc4C37jGCkL+g
kpXRL/TeXYYna0tmHQ/w1k/or/cCknwQB3hF+faK5Q3/CrvjKWDRgVGdQnRFzSrt2KKcnlyk
WqaiwcJk2MKS1qRBshhdVphNo11NF0xFU0ukJsk0bF8gm4VfY8aBF4LmNtwrbkbj5KH7I1Y9
pCcjzjVSLrhdVrgQNJ+LBvxJ08qhS8NNOdn3AEsetetBlslw/Efjr9Kmxl0wOco6a/zyZnm/
Q4PQb8NJsneA99IAslLzQ8sv8Ga61517pDUIX+DNdK9iaZqcfPhC7/0WOxfWdD3xBd6bcsRW
NKnVdWCX9OpdHMHDuMJueooIA4GGqktL5lB1clrxL616F2PLU9FgIWDCyrV27slWSlxjFtxO
nSs+J6MJdS1nrTGe0VTScjsrLFIqnkbz9aR93I4mTNdCSsrvFi09Ur4iFd77uQjhXDRO24A9
FNZeqWKe7C0xSTm9JX1Oh6NK4SQJTvpCWPFbh7DfZO/HRQiTJccB3pzSC8fzpJfhAG9meVSM
konvAd7M8pQKJMUUBnjzLrfniZDc5Rd4b0qvShFIJh0HeAXLO5W687N3eFfYHT8BK9SVqKFf
2KQnNZVsyWGFYheJlqlosIhzotYBuhAktdR80RJxmqs8y1Q0tXQFBietRpWSZo+xaElK76JP
bzhX3IymEoXbmlVqz5mCXEpvib0uXtwnpqJxviatdlC/eVXJ3pl91fcqB31Oh+M3PP/5azNS
keT9KFa9Wd7fZ3k/pUJonByDf2H3kgCG0p9zYamRjBd4c4deZOizExlP7Gaix1oUkofgAd5M
9LAwZrWPD/DeZF6IM1oymffCLunPuxi8HbYVdsdKQP2uphLKzNVP32TCSJdQCRQ8k4t4TEaD
4SAUCRYPyulr8ipTVrzB0PCiPW8qmihbUnN+1zweyLbTrql1Yj3bm68n7eNuNKgkyg3Av6vk
haKu6c+7rNxORROVWwOW8IPqgrS1cotXcpeT4WgPh0sBJ69MyYJerPo30jz6DgnCpLTZCk2z
f7LUHyUHtQ7sXlpS9akekBT6e4H3U890ofYAb93jSuB8Mj1SPdBbv0UnQyWajJKyKi/w1k/Y
yYpmPfcGeMGLxbfjnBYMSw27Y3OAUqh2qw1Fq2azz75oRZFP+kXv4FQ4/lKiDsad/Q9QVk1u
xQwZml7Ir01Fo6USWtMqRgJJ/VBdk5pDuehSHY4at6IJ7YPgNooIT+vq1IDIHMVJS6U8JoMJ
MQzR3kKevEoyX4NrZrUvdf4moxHARk6pm/PQtPDLW+dvGdH7KZ2/cABN6/wFeC/jEyq1ZWdF
DvBmxidFRbLSzi/w1l0maFo4WaUa4L1VW4NSs8JmL+zePcYawxJZB8OBXpJwPOd7bRhrtDtm
B9hLq42bcyNUTRpbxqIl882nDOkxGQ4VqGDO+Ay5Zh3haFLH4i8CMOdpoLlorFSu5ISvGYEl
VbdtiUy1X5fPc9tt+Grciob9Xmatd/B9saxDKS8yPTlN0T0mo4FirOEO0tWc76WHK2wJ42t/
fNRuhoMxEdyVwSlspaTBDr4Hgpcxvt1Sf1B6VudngDfXlcX/0qQY4QBvp3qQbiE8wHupHlYs
NUv1DvDe1B6wv0OS9Y0B3rvL0Z7aKEv2BnoJ2TsfFWnDKKLdsr3wKxtVIw6lXcJkzQ/WdPDL
qSnJYzIccm6ASFGTdWaRrf4vIRTYTjfnczIaK37ycu9+BEePZ5LrrfCLca53ca0YRhE3t4ar
VurAtVZI2oD7oiVSNhcT6HPRPGcroiMS/VlLdhIts7c7NzKeCwYLOb8T9ete42wSGScT/G+m
94uk/lSSWfYB3pzba8Uo+TwO8F4qoFDIX2i5X8wB3kv4/H1RGLOeaAO9N7unvWR9Rg7sZsIH
Ie2SVMX8Qi8hfOdTI21YRbRbAv79eS2ihs3Ekq0csWgJf23nRrNz4dRoHjYgQOphS5AdtFgy
gMrnImxz0VgR6ASdlZ1WJPt/fdGC7khnfBd3i+EVcSsaf5OEaVvMOgtrUrrd1ywIhi7mk+aC
Af+WnetxjKFLzwpLwpq9AbmgfFPhOHvziylI7Q1qTxen5/Sgfh3l+38AAAD//+x9S5Ikt5Lk
iRoC+wJ2gVxEHqN7FrPofoue+8uYRThy8SjuZQ4ikUUyKM1iL9RfhYZ7OBQGM9V/mttfz/Ym
D/BemRfLCyYPmgZ4rwBgKmhJZ64B3nqXO7v6hWTVbIC3focEUpolWwkGeK8MBSotaVh2YJc0
7F2cqo2QiH7HuV/iB9LU/9DKknRKj4sWsNFTM5vHJBuMw/znaKOvvJyMA4uLVvTrXQwGz7Lp
vYEI9trxhtffkha30yPCryft4x6bOCJsQtV3jFVaUhPNHhHeqelNsYn6nEB0C4SzZDq/Q1f4
MF5Z/c2y8QeNFAnAF6OsSebb6u8vbvUnyfPRAd58ghvNG9nxjAO8Wen1ojXZ4/7Cbr3HANAL
tqSX0xd6e9mWenb++wDvVXqdi0jyFHyAV2g9Pmsy9xV4BET0O7b9rQiyhTmHqIvm3G+/rbFN
0dN52sckG5cG/ixYB2MxyPZRlBXlYOh0bvU3xyaSykIWQSURSv4eVsWbnZrjfT1pH/fYYLjs
S7ghg7NKnkbjkikgJLro1ZtiU4tQE1V7pia3pN+QX7XGh/GiV2+KDhRfKP2e++bCJWy2Z7fU
dznvz2u9H3D6S97gA7t38cfIAEzOPQ7wZonn+2lNTowM8N5inlAx4tyCMcCbi3lWenKncWA3
l/LChDtp8vfCLpAQyBeL7oiG6Hf8+qOHtUV+rWqD7Colaw5rVS6686bYhCWcyzpllSbZUQxc
MrxwXcqbZGNE0siocTT9bzx6vi7ljWSIW2yiKscYRkMAhsnOyUWlPDrNSX5MsomqHAL5H60B
9mRQ8o5a3iSdHr6LPXwLtdU0nbk+nre++z08/iBbQxngzbU89d1Qdhjjid0s81x2WLZJ/wDv
r+VxyyrRgd5cy9OilqwrDfDmWh6WbGvegV0h9eq5yW4fwRD9jlt/K6wQ44OGVilJqC1xpQU9
PYN+TLJxZRByGKG3xpJMUoiLVvTlnVoGf06yoYJgbFIhDIOTHoy0KNPsqpI3ciFuscFCwC5A
ujGEgs1W8lZ0sj3LoNdP2k02UcmL2+JbpHAoSdoW1jUZyZeVvEk6Zv6bqb5k+r3RbM9RqX9L
o5Vv8fmDpH523IK30bIhkR9w+sNkos8Ab24bbNHFljxmPMB7JajUUrNWnQO8V4JSlSLpULaB
3votuqLMn3gP8N5PCFYgm7U8wCuOk6+kwcit6HfCBHppFTgivTpRtZw0iIsWsGG7EKFTbLj4
GmooQJG1lqw3xkUrjpPbudn0LBvAMBYhFwUMyX4uXjKpjYAXjQsjtuIWGyzVdTpz5W6QnAaO
a1aQOc3geEySgQJASgxMVVt2swMrBPWlAp0iEwoUGluXKDPX5BRSXPV3VKD/LKu/rHXyAO8V
fMQl4gyTvsQv8GbBJ/6rzm4vDvDWuxx5sKVmB0W+0HvllPYiybPOA7v181mtBSk5iTDAKwRS
vViER35Fv5XGwfEEcmTIccWsRSUvWbl8v3Nx6jdFxzeh1Qy7/+5bp2QPCi8pbEE/zT3+nGQj
pVdqqpWIjZL56HHREr13sbMY+RW32FDh5hKpNeQwl8x6O/OSA9kLb+c5NlAiVZdd8jXpLq+y
Rbo1/i+/fNJus/F7Ir6bbFRrVozDpDXPW/D9vNMfxIBq1vjlBd6s9Kj0bFbwC7tZ53HRlvUD
OcB7C3stCp6UrN9+obd+i01rWIwmTzoP8N5PKHHAmvuhHNgVOg/OhJEvviMlot8y74cCVcC1
RKTJWPIFv6ZCAcoXYyJTdLgYdLaq4r+rZ9RWzjZ4SVZwv2jummTTTc2sRdmVk5vHVSbI7ULn
jZyIe49acRJGLQx5WrIpEiYb1dJ9d49JMrWEuR/Xxi71pCbjLusSK/TrNsJpOtHdaa1j42SP
5yybt877jXz+mJOdegO8ucms+g4kOzNygPcKPn0afiYLJAd4b2GvR6ZENq7hC725sGdFLOmW
OsB77zP4bsK39MkBuoFe0VB4cZZrIyrCbvn3N//+esUGHVEh+ey2oisOc+Uiz3WODhfQpj3s
b305Tue2wYICEtjFUjzHppXq4hUR/WVr2UmltqaAhPrLR+3jHhsqtUNrFkYj2iin+uKiFWwu
TnPn2PhG03+N3NT3S1Ux6QbhVy05aT+N3P6cpAMFSVrrYkoEaUk+tza8Vd8PW/2pJetmA7y5
Z68Wyx6dDfBeBcBhKZvt2TvAW++y+BoNnLzLA7z1OyRkfxkmj3he2L2fr0LR7G5+gFdovH4e
qmAjIcLuhSoo9NjR91ZZW3bhXTEqBs+A1rOFd4oNFgxbSmR/L2UXqrhmhcI7LVJ+TpOBSDVD
cxWB2U0PrmkKq6c+218P2sc9NuBizRiFBKtIejx4Tb+e/vJBu8nG9+eda9f6jLNtSaOhuGpJ
x97Z1uhzng4JxVB9q0o1aWHqV70l3gKJ92NWf5Zs1hvgvUoPW+Ga7FoZ4M1Kr0cXR7LUc4C3
3uUOYYefjMUc4O1KL6ujntCtn46rS51kF9gTukLjnSav+9I7QiHsjlW/+G2NaLbeRTVrZSFL
chRA8Hxcc46NKxzDJtS0V9Hk4X9ctOLs9jTy9XOaTUNX4ByjZdWy8XmLKkWnJdavJ+3jHhvf
6BgSNf8HQZLmE3HRijIeXxSMp9iEm4uwa++O/p9kNMwijXd1djvLppO5WoWu0XVI2amMufLJ
W+P9tMUfJCe/B3hzGQ99P5jMCh7g7WU8qcnUswHeXMazkl/OD/Bmcdd83ZWkb+0B3lzIc52T
9XEe4O8u5I1cCLvj1h/qMzz+lBmoZVNSii6YfAE9bfZ/TLLBgiamHLEDKkmDIyy04uTZTsuS
n9NsgCk8ygnNavL3EBd9dyVv5ELcYhNFOf+hGkjcmqSH57JK3vnIzxyb0GtNKol1gspJa566
RrPS1VntLB2GDsKipKppW+p3JW+FyvuZSh4XSBahDuxeqUcRj56sogzwZqlnhXo2suOJ3VvF
MysVk2cMA7xZ6EERySYEP7F763jUS9NkyvIAr5B5F37ONiIh7I5Pv5YKzWL99acQk/Uiv2hJ
lvBph+Fjko1rHPHvqPVaqWryAYqLVtTyriosk2xibIG5m8YZXTpKeInMu5jDsJEIcYsNlC6t
dq4xZy3ZU46ywqf9Mpptjk00VLOvLr6HQ6eUL+atGbi92FFM0vFV0rcUDatW4WyDof0l4zr2
abj//tf//Ov//et//u9//gdU/+c//uv//O9/bl2okmv8XnmUHVpY8FJeoMJ/xOuQI/YwuRi/
sJvP0p8NK8kV6QDvfcgEwg8oucoc4M1F9XD4ThZvBnjrdyiqYa6YLAgf4L13mdgVAieDab7Q
C14s0M+tb2ykd9idSAUq0Ng3M0JWSZLtebRmnETkogw2ySYySHokzSlpcjMcs0sL2PTTGMDP
STbd37DSOsTEuv+ba2fra4aIn9ry+kn7uMem+r2JQnivho05W9JbcW8uR6Jn2XTfVETfZCVE
Tg5tzkaRpG0oPyfphKUkRXqP3/fKSZ/6WR/Kn1biv1e99Se9DllLTxv2HuC9ko+pmEqy7HqA
N0s+LVyTViIv7ObCOrmGS6dhv8B7BV/z22bJofIB3nuPsfu7DpMdnl/oJSfs5wFnNjI87F6G
h7/pDYEbVuOkyRktOfd0kXnR3DbJ5pldG41tvaVHmZbkm732eWer8BSbXnz5NaZmqNSTp569
4AoLHNSLrcWI8LjF5in4qlAlIFex6UPcJYqPTn0oH9N0em+E5vqVMErKWcW3xqv7QvFN0YFi
0URpvrEQxuR2GyYjNd+K78fNDlHCfS/pfnOAN0s9LJI90hjgzVKPIgQ5a3f4Au9tpiQtJkm5
PMBbv0NVLeEmkfS+eYE391EAF7Rk0MoXeoXYq2dVCl+CR1aG3ckwoMIu51mhWpVnD13ObXiF
2NNTf97HJJtnuFJksrgq7pLtgyi0JMfktGXvc5KNudgD41ZfjRDJN/OSCSB0/fKrJ+3jHpta
pPtPVYE7SBPMVZDiqhXqqF6MZ03SaXFvIvcDrGXPS8IxZ0W18qq8N0UHit+RzgT+j3TJKXGY
zAZ8i73fxfGQMJJyc8/uAO/VfOKLp2YHaA7wZs1nLuOy7eEHeK/mYyrakybcA7xX80GPuOGk
5jvAm090RQomO/cGeIniu+h3G2kZdjNfotYu0b/HVJMZXHHRivLe1TI8yaarUevWGvfsAE34
4C8p711MNUyxidzyRsj+PTXXFskuqbLC+9MV30UheaRl3GIT2o1q9IhGQTnblrNI8V22Vk7S
0WhFNMauWhukR05WtFYCXHjhTNGBwkJcXfFxOB5mZ9h5qvb6Vnw/6XZoUFr23TjAe1UeRLhU
sl1qgDfXfPwv5aTDzABvvctxpigtqUMHeO9d7r30mnUvP8DbD5p7dtRzgFeoPLlQeSMrw+6l
S5i0BqjWGDg5U+UXrWDzdAU/W3qn2GAkVHZf33yhUum5lTcuWsCmnY6wf06yoWJNpAJUJky6
V9DkudofRN6ZAP960D7ukXG51iLzo7nI03ReZly14gy3nd2bxzydCHdTNDNRSTsEyoqia+1n
d+dzkg4UUI3KfiQANcoG1s01775F3m/gd2itoGnSEucA71UB5H8ppOekX+DNWs8KJg0SDuxm
paelU7Ipc4D33mPD+EuTVdsDvFfpiRaoueLXgV2gJcBOTUp6PeIx4v+5pfMwmv85PIclr/OW
+FrLaV7dPBuFrgJk4dadTWBYolo7ns5JT7Kh0lBcGimwAOScoGmN5SG2Xz5oH/fIhGLTZgSu
9sAwWS9aVMwjOp3In6fTu28nXHMxMieLI4t0Hp7mk39O0okEyo4SQYKinHzW/KKp18Bb5/2k
56FRgayT2wBvLuZJEcy6fx3g7cU8yBrNDPBmifeMoEwKqAO8v5iX9cIZ4M3FvEhCS7YODPCK
Yt65RUmvMITEvUwJ4y4NXecp1vQu3lYMrT6rbWdL7xSbqMv5mttaOB8CpycJv7mYN8kmCnPU
WzcgoZrskl9WzTsrtH49aR/32LjAUWONiAwFSA6tLSrm4Xkxb56N/2yIBdFqy9YcVok8Op32
nqQTxTz2e25VkSXZqxsXvUXenxd5P1HMk+rPImWPow7wXhXAtTRLqtEB3tyeFx6myea3Ad5e
ziNMNvsM8OZyngtM5ORdPsCby3lSOiefwwFeUdBrpzORveLQE/eiJSwsuRCQmATTJbAV6kjP
7Vbm2aDrI2ok1f/ns3UJWzKQcdo6+TnJJjpj/cFRMqmcDu9dk/rRTjNMBpmPe2RCtWFliLAM
F0fJX/cyrffLJ+0+nQ7VhR4i1E412523Zrzk3Phwkk4U9Cp3dZnXBbLxDJOhiL+71qO01rvT
c541NVnwKlo2JbLb7s+fKE4mbwzwXmWCWjj77hrg7fqTIT0S/ALvrSjXOHRK1hoHeOt3qNgL
ZgMIB3jvXa4o8b3k7vIBXtI4eDqm2SsNjXMvw0ND4hiSYrjuJqtzK5pIQE6D2h6TbLhAcy7M
rWOtkqs1+kUr2DQ7bdmfZKOlg0X6TQNrLfte9t3YColzPno+2HzcY+NbbXTt6buCFgPOyZnT
iPBdQud09nyajjkNV9Lo+x3KtmDVNZVguCo2TtGBImad/SHu1nuyDzIC4P+OAvQf5ffXsoNn
A7xX8QkV4qSeGuDNik+epyhJxfcC71V8vZeadXQa4L31PK6lQvI7HOC9d5n6MzkiOxF8oFfU
HM8tnnvloSvupCxQAVKzRq2rQs+OBC+poMqplcVjmg37IsxMzKYtm9bjF62oOZ5bPE+yCbdm
fJa2oLmWzf0iVlk8y0XRkYequJfn0YT99yoVCNtzHPy38HieptOJjbRpZA33ZMNqXLVEwp4a
Dk3SwXgPCFLFpqLZqsrke+Ct+X7e8e+ZspW7zQO8+Xg5/tLsTOsB3i72Kia9uQZ4bxMBydPI
M+n49wJvLu+hq/TkdzjAu4u4tWC2RvqFXiH27KLAJ0NQ3EvAYHGlp7W5qM8OJaxIyYkEkfP1
d4oL+w+eWa1rx4qcYxMXLWBjfFHem2JjJWY0wVfgqqhJgzxbUnq9HhiRISbu5V/4dqdXitTs
1izZtbpqYIQvzpcn6WiUw7ULQZyWZ5XrCiPx6/LeFB0oirVaRXNZbMktX1z0lnqLpN5P+f0p
t7zfX4A3l/d6UcgmuB3gvVpAfXHXbLTXAd6r+FjCOiVZO3ti9+q92gsmcyUO7H6115NHnwO8
4jD33OvP/4KhKO6FX3AV10bqosKX4LTX3wp9JHgxsznJppmE8xM1UkmeF5LfnCVq72JwZIqN
FVJX4uzb1tak5rRrXLRE7Z1mtw02H/fYPEctEEU6CHdLd9+t6I2kUyX+mGbjIhya1d5Usvcm
LvpurTfFJk5lDboxoDZK3hu/6G/ZS/i3d/rrljwkGOC9+g6sGGCytHyA967+TP6STfbdv7Bb
7zFyKz07AD7AW79Bqn7bLHmPB3jrJ+SI2dNk5XuAF6iIpzPD2brbhoq459vfMBYpJWyUTOaG
JR4jLnwv7F+myGAB9d+8KXW1bEEYJwcc/2D/cuq9NsmGCnQnwtWlMFFyw0hLeg8RTuecvx60
j3tsXKvVuC1QXUK0rMVIXPWtzYePaTpK4VYowrUya1rirTi5rVfjIpN0DJvfFm1Qu2VNJevk
oNVb4/0eRn9KySCvAd58eMulU3LydoA3S71etGcPbw/wXrHXrXBPJkkO8N673LlkzRyf0L19
hP6VNE52Og7wilLelQdMH2rinl2/xUEnsUuJ8Kbd6gHDZ+vVY56N752aS4qKmrSKimsWkLm0
gJkiE5niShoT2w2eMRo5C5jvHaT9etA+7rF5DtI2VxO1KdbkWdGq0I7TKefHPJsWMi/OoQF8
Hdw55Xzh5zxJB3x7ILVHXKN/WS25ck1GAr5l3o/6/GHp2TmHAd678qM/WJWTviUHeLO+868l
Ozv/wm4v5Ul2+RvgHyjlJWfZBnh7Kc9fhMnfyQFeUso7TVLo1YaMuOfV3wilIyiiYFrhLanl
6Wkv+WOSTZTlzJcq61rFkkdoOJk8cKeWN8WGfAnVxmiVhDC5H6OCS4pfdjHvY0NF3Ay5qEgI
ET8SRbDs2MKaWt7piMxjmo761tdcSbErPYasxvv+Wt4kHcPoZyXn1NLprO9a3l/b5683Sk47
HuDNtTwt2rNTtwd4d9NWGPjmfVYCvL2W52ti1ufvBd5cy+uFBbIRci/w3nqeQUn6wLygC9TE
VWgHjGAIuBvaIa2GJ57/N23nvOTQ9pTM40+Qqf5/rbKRZRsn1iSQtNPq1+ckG/KvWawzgd8Y
SGa8+kULHrTLGQwYsRC32EQdq5HzgF4rbS7m0XkC75+gI91cEvlXBbR3pOSqmDdHJ4p5tUJv
rsPFkvM+MNkg8LvrvG/x+IOkRxKssK3767r83fBw1p/wcEZopWny7TXAmyuNViyZS3pgt95j
wupiLVu3OMBbv0F1was12c8wwHs/IfWClmwaHOAllcYLWTAyK+BeAgeQakUzir7Bb7V5+Hcy
p6Z4j0kyXMRaRwNQDMeX5AzwnFHZHyz+zoO8ZtmgSGM4/k2WtcuKvPY4UPzVg/Zxj02UDGv1
28OtiQClx0JWFBprv9jqTNHxDWVT33RoU2HIvu7Lio6SC8PCz+mbY6ZQYy6stQ6WNWefC+L5
3fXnP8jir/k7JtkSNcB75R5x3lNlgDcXG59GLlk7kBd4r+CzXnoy++zA7hVTLoJb8qTmwG79
fC7QS3KC5QVdUWiU86Z9GIEVcCdFACPjoWEFIfVlK7dg4ZLmJ5ALh905Nlx8karI1uKf5Kkl
TzY//aFr8GL5nWKjhUQIDRmsQfLwRxfN/8p58wKMvIpbbGpRiGzC+KKg553wVvRiXJo5z9EJ
lUNhuqgm6HrvW6XRv+vW08H5z2k2gggW74FONZtsX+Z6jd5C73fw9SNNFvQGeLPCo9Jb8iBv
gDcrPC6anWEd4L0Kr7vwrcnRiwHe+h02122191wNY4C3fkJ/rApA8sB7gBeoCTr1ePD1d0RD
wL3YDu4Y85nRPyi51TeuWdE7KOfTIXNkOJqZOSypoXZNBp3GRSt6By/6uebYiIscbj0O/Ju0
ZJlF1iijerWlGLkQt9hEQBELgesi9Ucu6c1al3gKub48062PaTrdHzFiY8EOmjzw96vW0Pnl
s3abjlGM/7bm/wFMGgLUyf6Ft9T7jXz9WrId4sDu1XtSC6UzO57YvWpPa2ktecA8wFvvMPdW
ajIN9sBurudRiKNsE8ELvPceo983oOQsyxd6SV3vfEYTRigE3Iu4CONW0O5/Svbkxi9a0kF4
4eI8xya2JrX64hu+uskfIS+ptUA/NRb5nCTTSqcW59G+IcRst29bol3xslN1JELcYlOflaOQ
etDEdUX6AHeFeKXT8+jHNB3txgbs31RFzBv7rbAprHRR15uiA4UEKogouexLj9HTVO/RW+z9
qLEfRrZFfho4wJt79KL8ney3HODNPXpYzJKRQwO89S5jbUWSq/mB3foNuiwvqsmncID3fkKQ
AsnX+oFdIfBO50193R1REHDPnp8FWmfXJ+FTlj1/4hVuL3qa+vWYZIMFRaWJonA06SWrkyua
2kJTnq+6s2wqqcTsE3TS3K4b18wCVzxj8/WkfdxjUwu7boRGLomga9JSJK5aQed04uUxTccf
316FIea0ITkP6FetOFZ/BgRdP2v36XBl/9mYsghCms67nrdA4v2Yrx9Sso35AO9VetgKYfJF
McCblV4vtWf3Qwd4r9ILX2bWbLDdC7xZ60FpWSvxAd76CTksI5OP4YFdoCewXmi9EQQBN+35
G2mLFOheMVuEXhIsBXLqYvOYZBMWLlTZt07dV+BszX+N70uzi2reFBvybSpHdEKvkN5XrGkD
w9Omtq8H7eMeGRdt1qtGYxv1iJjbOo2hF10Ck3TUX4qq2IQb1+Qc/aKUjsuj20k6/pjVCrU2
s9rSFs797e3356Xefm+/xknnvAHeXM1Dl21ZJ5ADvL2aJ5yduH1it9fyarI28IT+RCXvTiFv
ex3Pt7vpOp5jl2i7iyV3ZEDAvXgOFqROLC2iBrIjdovqeGe9X49JNlGSIw1lwr5MJcODl9Xx
zuN2p9kAsd8bBVJKDsTFRUv68i5GbUcCxC02UZGrIKoc1sCcfNQW1fGIL05qJ+mo+L3xTWVt
LJp8ky4Sd5d1vFk6XCms2wW4Ze3b33W8v7KnXwx+57a/B3avwoupiuyQyABvVnj2zBxKm6oE
eK/Gk16Msg7YB3i7jrKedEce4L1VvBahG8nGhhd2gZq4CmKDEQIB95z54wjNpQT22rKmKovc
m/k00uIxyQYLALmYIBcSRMko5LhoRU/ehXvzHJswYu7dpCK3tG8HrVF6V0kwMDIgbrGpRUBb
uKnU2jqnTfDWTNpeCL1JNq69XeQ19V+3WnpiYYl5M50W8z+n6VhY92A4qvuOr2WFnk3tkX53
oYffYeqXPNNf4e57a4QgOTyw4A25QBT/lNFgx2RL9ABvPtp2IW7ZQ6sDvPcxEyiQ9SN4Ybfe
4xgnr5wUnAO89RsU7QWT59oHdvO2h6QoZM+BB3pFG+NVUWrEZsCdKAMtgGIdItM3YlaTHiew
ZE7ldOrmMcmGShOD7iqS6dkkmVKRS7oO+lVFaoqMFTZ1Tex7B+ZsG4WtigA5q+V+PWgf99hA
YRbfd4kY+RYs63Cyos6OJBfuM1NsfOWLTkxsvgNTomSRZvYo+N9vDp71ZH5O0sGCHFsvFN9N
GmTNCeb8NH53SfwP8hnU0mvWLvcA71V7TMXS4boHeLPaU39NJ8VeQPdqPcKillzVB3iv1mv5
qekDu/f+klrB7I/kC73iqJvPy1I4kjPwTpqBlNB43VzPSxfObVFksvDxh5nk85GVOTZUtDdC
8D+0YjoHZMWgqIu98zbGOTa9NDbuHTgifZMlQ79ohTy6Ens4cjNusQmx5zuKBjEcZS09HLVi
xPpK7M2xCdnmX5I/aNKrQbKlaZHYq3bexjhHJw4B/KdTiXr3XVLaXP7tNbhI7O32GpSi2QVs
gDerPCxCSZ+qAd6s8qiIZAeTD/DWuww1egBrcl7lC731W1Rt/sUkB9AHeLeap0KSNpU80CvU
3mnqhq/BI6cC74QHaFGxJoxq2FvSok+XjFmCnI55PCbZcCGONjOu0Huy14wnfTT+Xezp2dn9
5yQZqMUlJDWVZOHoecEKpXc6E/H1lH3cpBKZ8c3EvyXqmGy0iYuWHHWfN1XMsamlIWAV33wR
4bMFJaX0VhT3/S8+75+dvTnaLXybMMIfk8NRMLlFeiu938hqMNuUd2D3yj3hgpbuyXuBN8sA
K2E5mlQBL/Buued/a09urA/wXrGHYaiRvMsDvPug3kVwsnA0wEs6Gy8W4RFUgfeCKpgRjbp0
6pD0ltYl5RaQ0watxyQbepZbKvaOPWZZkoW9FdWWy1PcOTZWWMH5dJVmaMm2C7/ou+XeyKm4
xeYp96yTgZpy8kx6kdx72hJdP2k32YSpTJPGMXRNwj070LuiY8dvzvkp7uzN8V+Lge8lm9ae
zG6ASRvzt9z7UbNBKJL9+Q3wXpEHrtso2WU2wJu7uKKmkDxbHuC9dxnDQxeSQ+gHeO9d7lbS
/mov7F4RWm+M/wzwimoenffp4YiowHvpIUaNJKpfnXs6J24uNeDfJV6/OLudZFOryyJBRHU9
nD2CWmIofZUIPMfGX17QpbqOYNcQyXN1v2iJP9+vn7SPe2yq72af/QHkr5Tek2ancdWKw9t2
UdKbpCPRqte4sTWrycZDv2pJpx5clI6n6IAvlL0DsJhpT9db3516KzTeT7kNNkoePQ7wXhFA
rWC2P3mAN0s931Anzx0P7GahZ74TtaScP8B777GRC5BsHOAB3ttI2HuR7Pn3AH+31Bv5FHgn
MwBLj2Pbbmox4Zv8zktfIVzlVBw9JtlAMW2V/IFtStncO79oidtgOxsw+ZxkEw92pxggNb/z
2TnHJTL8WuqNdIpbbEK0kWu9mPBCVdks9c5KrY9pOmLhK+1kmv+6KTuovETqPZ1Erp+1m3Sg
QARGPmdmekv7FcyVAN5S74fdBrtl1/8DvLmcJyW5sX1BN+u7eC+nBd4LvL2UB8kPeGC3F/JY
si4iB3hzKS8OxZKu6wP83fpupFPgvXQKY5dE3T+gsWWHm4qtcRy8aMybZPP0Xfb1j3zlbVnH
wSWpLpelvCk2cQ7BpAh+h5ppjk1c9N36bmRT3GITSq2ybybI4mQw6euwo5Q3SSd0EFf2n07j
5FTJjkreFJuo5Cl3RWNpkFz835W8v7LfYC2YdQ0f4L0qIBxdJOspfYA392z5X0rp/vwXeK/S
I3/jZKs2A7y5locFe9ZX8gDvreU18/dcsroywN+t9UY6Bd7L2ujCQoL+GPqjmFVHfY3Wuyiw
TLGBOIRu3RA7VUs3GC05hG52UcubYkOlcyXXrs3FqyTZ0Joc4EutN8IpbrF5aj0l31QAWW9p
/+IlWg+vtN4kHemM1MEaStPk3YmrVtC5as2bogMFJJwgofo7BpNvtvAG+zuKPfoOz8Hkirti
rf1ru/slEwoHeK80QS3Skj+PAd4uQJmTIn6At97lBuFolvRrHuC9pTzshSEZ/jfAe+9y7VYs
axh6gBe8WPjKiWNEaOCdWAOOZCJUfwg7dEnaUsZFKw6TTwcaH9NsoKmpVKIGlhzQ4iWzs2B8
5ivyOcmm+b7FXw8RXSdWk8XGNlkBujMaMgI0brGBMCT3S57/Wjbac4khOcJpLNBjkk0tEcTH
lVVa2Elmk/hW2OFeTwJP3pwWcUC+NVDfwWWNLPyiv6P+/EcZ/LXszNkA7xV8Qv4+S/pNvrCb
5Z48872Tcu8F3nqPDSxcuJPusAd4bzWPY1uefAoHeHP/QNMSmVzJBoIDvUBUUL0QfCNJA+/E
G0ixaqbasZqQ5Sj5RSvOYwUvugen2FDhRmHyR9pYkz3GtKT/5HoWeIqNFe5G/h4zUs0aXtkS
01CsdJ6ngyNI4xYbKIyIzVyKE6XNsdbE2Z3XTx+TbOKoSGKTxNaatGQ5qa4pB8NFoM4cnTi1
8d+MRdFRW/LNFhe9Bd8awbfb5E+jDyf5RjnAm8+WI0kim+F5gLdrPajJzPUB3nqXfZvrEjgb
C/+F3lzci/bU5GowwHvvswKWbLftAC/QE8Bnh2S+Ao+ECLwX3iGEXaiRdtBkMFdctELr0YXW
m2LD/lIS8yUYVdSSxxR+0YqTfzuNx/2cZAO1kJkwWFT3klrPL+IVVim1nx1gfj1qHzfplGoh
90jBFR9lreTqCulKfJ4TM8cmLFz8KTNoCv5H2tF5kfHLRSF58uZEaGKLfBUXsZLty5gr8r/F
3m/k8wc9WWgf4M3VvV7yue0HeLMWqCWZPvGCbtZ7WAtkz8O/0Hv1Xo0UgmRlZoA363rTWIuz
wv5AL1F859U9GjERdMe73z+asrA26WaWXIbjoiXVvfN+wjk2VKJAIUDGxC1pUU+lr7CB6Xq+
Cs+xsWJizBGjB9CSq7AtiVe5FHw0UiJusXkKPuoxhV79YctqikWC77y6N8fGpZtQjckeVH0Z
R+cE34p8Fcbz1tXZm9MAhaJxgECSc9tx0Vvw/enZkf1Of+mo0QHeK/LiTNGSL+8B3ny8R4Va
NhrjAG+9yxQzyUkfvQO79Rt0We7aPDkyMsBbP6G/CqObKvk7OcBLOvbOi3o0wiHojmk/hvqs
0efmGqUncztwSd0I2C4k3iSbaAM0FEaz9GhZWWK0bacJep+TbPzVwCYYBshiLVmHpyUxJHHS
+qsn7eMeG5c3vs8RdQUR7qtJe4I62RX2h4HaM8X6mKcTE5PdZR76NjjpkelXrRjePu9A/Jym
Y027KnCrvpuo2XHnuQ7Et8j7Paz+ODsgPMCbD3G59NaT8xkHeLPW677NSWY6vLB77zFKOJMk
O9cP8N573Kn4aydZtD3Am4+Y/cGqSeOUAV6gJ67Gg2mEQ9Adx36MoU0jIIA48kyPB68o5z29
+M4W4Ck2UKz2Zr70ck3PmsCa1sNmF+vvFBsuWIE6+BdFoMnR7bjoW9vbvp60j3tswqtBkGs0
t/VGyY3SsvHg80GgWTrSqgLEniIG67P1PFlygHvhBTNHBwqKWLgEiAFmMwnKXGvPW+r9qNUf
ldrSVn8v8N71H6FUThb8B3izxsOS3n0P8OZ6nhaCpN/WAG+u6LXSIZnPMsDbK3raskr5AK84
tD3VRb72jnwIupd2EZ1TER2PopocJcQljfLXFb1JNjHn0YhUDblnk0i+v6I3xYYKKcS8DDG5
3sseQa84UI9H4ldP2sc9NlGbQ9Iaowy+oUh2tiyq6D3n+K4ftdt0fPeGzTeZwhrBc9mK3pI4
3quK3iQday5WjUT9PUDpEZM5L/S3zPs9LP/8vZ+3/AvwvU/4/wEAAP//7H1LkiQ7juSJhgIQ
P/ICuQg/RUutetFdi5n7ywDuxlhUiVnC+BiMyFcu77NSZjqc5kYlPqp/le05+dCkWNSB3dy8
BQWzpdsXdi+fp+i5S7Y4DvDmfF4roMl2pAHem8+jkMlJfsIB/up83rCHoJvWHc7vSJAMnXpl
a7dL8nnSLwpqU9FEaq4REqg2v0FlFWpXDG9f5/OmouHidyyqhK1Hh17ape3L83nDHOJWNJHP
a12AmZqiP8pbpZ0vVMRnwxET5+EVjJSyzZOL5P4u83lT4UQ+rzUPSP2alL1V/F3zeV8i95c1
U1hipPBnC/4lE2UDvLl50Ipl9V9e2M2pxl6yFg0Hdu8Fg1vRlqzmDPBechfieFST88AHeO8n
NC5JqvaCrqCedkEIhnMF3bEToKLSauPWyCok4/FFS2QL+0V9byoaLgoATm0MnAlK7n4aixZE
0+q5+u9sNH63ByQiNpGkR0os+mrqOYwrbkUT1FPD8VgYYjwkW3tdQj3PB10+JsPBAqZ+Z6vc
fXOSj5ovWsE84bTW8JiPRvwFygxVELKNUL7o78g8/6OE/lq2q2yA9xI94rxAzQBvzjRKjLxl
lZ1f4L273K0QJHONA7yXSkUGNtvlP8B7dxme0kItuc0DvYTyXYxoDgMLumMqwMWJV6ghc2Mj
Seagl9AKlAvF3dlosGPXKj0KsckJzVi0JNt4Lrg7F42G7rZEA78TC00WYnWJ7vb1MPCwr7gV
TXAk61artJCsTA8DL8nO/f5Jux8NiH9JtbfWBNIcaYlS9YW1yGw0iobQa2gmtfTezNXI34zv
Ryj9ZS9dA7yZ6tHTwT5J9V7gzVSP/UeT/akc4L1UT6gIJlnKAG/9Do17oaxk8gBv/YSdtFBL
KtMM8AqiJxcjwcMogu7ZXtSqRg2ato6Wy+2tcaVF5YuEy2Q0YX2sz+NXe1LciNd44vVTKbnH
ZDT+ghUNs9swX+OsqU1Z4Z5dEc81nWn4RNyKJloBRTs0INLO6bLynLLIv6Uqz1SQP6bDia5b
rkqtC98wQP5aU5LHZDjBQRHZ6R6iZjX/Z4nrm+r9IJ0/tfQ59gLvZXwChZI39gO7l++pv6Eo
mfJ5YbfucNNaODvQMsB7E3vsFFOSRdIXdu8OE4WwUFII6wCvqHziRXVteETQPf8OCsup6Ouq
1jjHr33RCseLK03nuWi4AJBRj1ous2Wb7mCNwt9FqmUqmlaIxDmrCGqvSRkEX7TGMZh/96T9
uhcNlF79RWL+X0PpkPvxwJL+TifMv33UbofjvBVAGvcWkntp+ZevdVd5TIaDhUn9UtGiXzWf
pOS3pvNfnxXZLfFXS3aA4And3KEX6fLkzWmAN/fokf+lScGSAd66w/6Odc6b7IEb4K3fIdVa
LFsVHeDNnzDEepKKay/sAg6Bp0MVfuoOXwi6p9XfsSFI79Xv8EnT10VDFSoXfXpT0dRSRZtZ
7ULZCZ462ef+rzVbvEjlzQbTmwIFfwjrrGQ0tGR4Vs4mmz8ftF/3ogG/hBkTY9wmLNsc5KuW
tOmdNjt8TIfjT29r2jwW9YjSCs5LJrX5jHw/5sPR9mwJDYEhTc8CzzmQvPndz1D3a5bUVRng
vVSvWqGsq/oAb6Z6rWBWh3iAt+4yMRQ/35M85QDvJVIhwZ19Dgd46yf0w7fU7IDXAC8p3J6n
WHhYQvAdnf5gFMpNGE1NeSejQIHzI3g2GpTOBH64i/asCmhZQsTbhUPqXDTk0TBwbFDMZGSV
X1bo2Djz/+2T9uteNM4MQgYvGlYtJPGy+n4rbsKVTgdoP+bD4cqNDLA5d00XbvVrU62P6XA6
+QoJ4ZcmmBwo9FXvbN5fZ3vfIPDX0yLOL/DmjJ6/k7NNvAO8mebVItl67Qu7OZ8nxV+xyW/w
AH9DPi85FzzAmz9hz/9OBngFybsQXeNhCsF3hPoxRpa1M/t1KKzjsxm9Jd15p72GH5PRRHaO
q5oZV7DkUMmqlB5fkLzJaAha4yrCYfyVFeShFf1ftZ135/GwhLgVTaT0mm8NOAVv3dIV2yUp
vStTttlwVFiqk7zQcrak/9EiU7arlN50OGoMzX86RuksxTul92fL+1lPim+8sHuZXgxXpKXf
DvBmpteLZGduX9i96TzFoj3ZeznAm9N5VF6Zq1Q67wXe+gkFuPSabA8d4CW9eeclNR6WEHzP
rsP/TAWhbtJb1q1jiY6z6hlt/ZgOBjo1rOD/pAVj6hKD10sd57lonqaNhGGeoKG9mNVxXjOh
ej7ww8MP4lY0flTUWgUxMseYPWJi1Qqid+HzPBuOVqkKFJN+ijVrZfblzmxz4USPk1/o2d8w
fptMOsP8Xccw6h+v7ndrkCA5Q7DgHbmAFX+X5mAHTE6uHuDNZe6Y8EhaKg/w3sdMQgsUcp9w
gPdmQNlqCX/4pHD4gd7LO02LZS8XA7x3n4nZz+xkL9MnekUWtJ/PrfAw0uA75gaohbh16sHB
sv1MsWjFWK9cUZapcPwu7F9SNyOB2rJp6iWDo9hOrXEfk9G00vw1y6jVwzHIbU4sWpIGPUvq
fj5qv27vjTQhM1X1Pz3Hv2iR/uBpbfhjMhrwr7n7r4aY1CrlfX6XqEP2iyzoVDhxQ2xoYlVN
JZmijhrj35Ec/wcJEFqhrKvkAO9lfX54AmeNTp7YzZxPo46d1aR5gTdzPumlYzJRdID3Mr5O
oRCenJk9wFs/YXfGAz35CQd4Bd87nYX1Q3jYafAtiwMphjGljNg02Z/1XPPVdG8qGoraTO9S
AdEs2agZi1ZUvU9nJR6T0YgTpFqdUJA/PclgZInAjrO93z5ov+5uTQMAv1G0BmpJgZ1Y9NVs
byoa520YuV2S0LnMvgkWDV1fTSnPhYOFUbCZATkXx5zMJU6WRN5s7/vFB8WfxGRT0ABvpnm1
CKbzUi/wZqLn54YmmwcHeC/R00oFNJmD/0Rv/Ra1WUHLCiQe4M3JPWpFJS1J8wQvKXuf+xfz
sK/gW54CVkA6OjsKV6tkQLZE4g71NJqPyWi4sHbogiaMlHUW4RX6Ou1ULegxGUwLvb5uCOS/
wJ5UkWhr5PpquxhiGeYVt6KpJUSZoVXo1SRJ9WLRiqr3VSftVDTg18vqL/AK7FSvUXZieYkG
OOK5ovlcOKEtEwPl1YLpQZrqvZ1FVlG97xIf9FtxMmFxgPcyPuFCyaTUE7qZ7XV/P2m2lPsC
72V7kQirkrR3/UTvZXu+caCYTC8f4L37DDFEk2x7GOAVib0rtjecK/iWn4CWaI5XEn/fCyXH
WWLRkszeRZvjVDj+LISrrLM9X1fT2tlL2hztdALkMRmNFupNqAE4o4CWNNopvESipp1Ris9H
7de9aPxHEPrMfgNvCGzJ4kxZMQdWz+fAPiajCe1spA6mTSBSfFm+tyRTeZp3fUyGg/4bUKvs
BNZaTaqC4LuQu4DvbRcgxGKUPF0HeC/HQw7/iOSF8ADvPf85jLWSmdEB3szk2c+BZGf8AO/d
5V6LUjKJMcB7C8zaS89WOwd4AZFAvpgwGLYVfM+2glWxKVKllylVjkisSIOpnjt6zUVTC1QB
P6o0jOmySvQFVoxgm53rEM5FQ6UzV+2k3FU1W4xe0SjgTPliaGqYVtyKBksHCLqFYPI0vM2N
x69gRXRF8qaigSJdEMi5vf9uWtJgF5Y4UzulvCB5k5uD0hF8Ua2RRc6SvKnr/5vk/QwVwqwO
woHdywHISvgeJEeWX+DNTK8XsqRt1QBvrtJrkazC3wBv/Q4JXiOBuZPtAG/9hFyhACdFxQd4
BdOTi275YVrBd4wEtETfD2q0ZL9yOCmmV1doEKpcaIZMReOkDauYtV4xXSBc4dyKdspaH9Ox
xPi1VrXQp8n2rKwxJ7vkecOw4lY0WJqGcbN1vzxCkoPjmqkMOk20fkxGE4yN0RlXt2bO+HK0
dRHPA7roE5gMpzH7xYhbDfHJpEhVrHoTvb9M9PYLEFJaZvqJ3ZzLCz285FjmAG/P5QFlM94H
eC/DY983zppAH+DNDI+KZsdZBnhvLq9hqZxVbzrAX53LG74VfMdLwAk8xxFlys64kg16vmjN
5O2FyvRUNDEL2BARSEgsmw0uuITjtbO9eUxGEy+HsIsz50aN0+2GK3poapWL3oDhWnErmjCv
wa4A6JeJ5FB0rFkSzLk58Fww8LR1BxNlY3k6OeYo3pJRjNOp6Mf03vjjG12gaj2S+tlU3tTZ
+mZ4P0R90JIztwO8l+pxDLdnO8sO8Ob2vBjIynbnPbGbiV4tnKyZHNi9NA+tZOeBDuzeNJ6z
8/B/zx27B/iL03gy7CrkjoWAOv8UaNH9pa0nL/C+aAnJ4/P0ylw0QfKi4iS1hp9XmuStSEra
RXZlNpqwRRFtDRphUpCkfn3BVoZZxa1osLRWAaiDxPRCOpG3Rkrx3KFwLppQEYybBJCz7+iZ
3Kk9SHKeM54NpzUNEu6PG0S/QzaRN3Uu/HSaR18hPpjUrlphNfNHi/z1pITeAO+lnlUL1+TM
1QBvp56M2dfrAd66yyHJ739rMs34id76LSrFwFz2STzAe/cZlf31y8l08kAveLlUO880yrDT
kFtWJ1isktMD9K9Rs7qFuESXGOVUyPdjMhyn+52YVcTvnZRsL45FC6LpfJace0xGY2Hiox6K
Pz7IyQSQrRk3vZoNkeGmcSuaWkycDfq+hPBLMtcYi5aw0N8+aTej8ROwMUCvztsq16S0a6xa
kmu8YKFT4Tjb92sUij9papg2MW9v2ZdVdO97RP7Ur0XJzMMLu5fzCfm7OWt3coA3cz4piklz
zgHeuseVei9Uk/0Dn+i9lVvmIJpJmb8DvJvbx0Bs1sJwoBfQCsJzezsZzhpyy+1AwvUEBEk6
UFL+MRatmQc+l3+ZC8fvKH4UE6DzPT8Yc6l1KrIi89j5XJRjLppe1FrXzjVcjJOXyb7G9RdP
Z7U/H7Vfd/fGYg6YwmWnSs8KOy9RsznvufuYjCa657A72+tBy0GyoyIr+mDi2f7do3YznBov
esLW/U2lNe0XNKe38eZ8P0HqL5oJ0lJ/Ad5cXdYCaaZygLfTPbBkXmGA99I9rf4TzeqWfKL3
pviqhbJCUurvAO/dZ6utJInRE7qAS/DV6TtMIuSmg0dH8JNKBU2zAl+6pL0LhS6I3lQ40URn
LboI/e3ESQUmX7SiYN7lfCZ4cnOwIDsHR9+hSLlkM6+4RtT5XOlPhkvErXBCtI9AWwwjNEsm
khcp/aGcq4fPRRMevg2jx7o1vyMlC4iwhoafNwA8JsOJoZzI6okgsyRtmX3R28d4FdP7LqW/
BkltiwHenN9rxWqyW2+A9xIBBb8lJecSB3gz4QMnwsni0ADvpXtOKRQkKW12gDfvsobCYNrj
7ECvqOheqP3JsIqQWwL+0SLIqpW6v/STXhG4qq8Qznv658Kh0jgqoKC9dUsmKWiJ9QW2U1eS
x+zm+AvCg0DnFAyaFOmJRWsE8i5KusMs4lY4tXgwxlyJGvYkh61LTFZqvWosnIrG6ZsiYNeo
LiRJUqz56oLuVDBYrPk9qXWuXI2zIj1zSoxvyvfdYn+SPLsGeC/Nw3AOS9YyBngvAYiJ2pY1
vTrAe0v1Pa7+yfbHAd76HRJY2HgmR0cO8N4yM2BsXO47HOAlmb2zt7sfvMMlQu5ZXrRQ5qh+
VkHWwIMnu3X+leKdGox+TAZTC7IBaLUaHbHp0ZElFA8umvamoolytEbHHjszgqT565py9IUd
2OeD9uteNFgYhK37dUIlq8MYHmILoqELU8C5aGLUV8FpkbNv8dvEzskRoItWgcm9cbIqzRl4
JMST0fiid8/eAor3XVJ/jZLNZgO8uYLLpUPSCm2ANzO9MEtKZkVe2L1JW2xFLSvqfID37nHj
wpItMB/gzfXlFhqNyamvA7yATODpcKAfv8MdQu65Q4SZrJMidCoKaSGYJUYkeio28jEZTQiH
VAMh6v7U9rRw8BIhmH5B9Kai4RISJl1JW9Ws76svWkEm6qmszeeT9uvu3rQwhsBK0IyynoCL
LIbtIpU3FQ0UMQxe5MSoczacWLWiHI3nmkOzmxONOsCg4sd6WnF7LonyZnrfrPWHkJwmGuC9
x3/1K4Qm0zwDvJni1dIteVV9YTen8rRY9ix/Yfcm8pD8kphMNQ7w5kSelmxp88AuqdVe1M+G
L4TcEevn0qI3vlKFzq3nAuLJvpx/K9Ve5PGmoqnOOzsxqWpUa7P95EuGb9tpHf0xGQ0VYQ6T
C3HmbcnsSiz66jzesIW4FU2k5AgUtSlwTU7XL8rjXUrATEUTKTluYE6DlfxylPbs+PJE3uTm
QDU1EYQeXYfZRN57EGMBvfsuob8ulpx3PMCbE3la1LJD+gd4L8sT8PMmmch7YTd3X4pvW7Iv
b4D37nG3gllF5wHenMizopgUxBzgJYm8C7G/4QwhNz07CDu2FooeWW6kS5JFqHrRlDcVDfqd
qbGoR1QbJufzcYn2hf+Mzy2z5qLh0NltjXsH4OxbmZckWa/F/oYxxM29adqotl7JglR8aa//
v1ZsTzWQPyajCXc2QnYKSc6OLDl/H6u+OpE3uTlVaqt+2XNWbEkdXZzszf3pTO9LtP6wJpu4
6oqX0bIBkf1qf355yqv9BXhzy6AV03TL4Au8nX8CJqcaBnjrLvsj3vxFmByU/ETvZXg9JLGS
v9kB3voJDWuBrH/hAK/INp4WxZwZDOcKueMn4NvburH13oUxeZS2JUcpcr/IAU1Fw0VBwWrX
xph96/uiJcVku2jXn4zGWLWLmt8OslocvEgcjy446HCuuBVNGPRhKBZK80tCdr5viatfhXbu
XzMXDT5/0kTiWwPUsqRthZN5fWYDr5+029H41pBYPGadkzUHnHTj+ekU9D9I6c/8KU5mowZ4
L+MjLpAVBRngzYxP/GeQloB7gfcyPsMocmQlqAd6L+OTWiT7LQ7w3n1G7PGSTKa1BnoFS6rn
eUcdRhZ6y/ohakutcuUOJFnhotna0r+VmM9Vd+fC4VJDLcU6ScNac0VZX7SC9PUL64e5aMw/
GJuFQA9USus7r4imwikh/3zUft2LphZlUlbsUPUpuJwifStmES/1neei8Z8ANIYG+FTIy0qm
LKGweFr+f0xH4xclJ3vk/2DyZ+Nr3gXmRZxvt9KfFuQklRrgzWSPSksWbw/sZqrHRTWd3HuB
91I97uI/0OyJPtB7U2eCpXPyWxzgrZ+wdz+Ako7BB3ZFao8uaN5witA78v2hGgzmHK9WBoNc
0S8WrSgv83nCZS4aLo43ATPQdIoiFq1I7V0occxFo6G2TYghGNw12byvS9S2nUmc7c3nk/br
XjQYHrvgNxUWxJZMi+Mii93T383HZDRQml/f/F/xvUkPLsaqFeGcDlg9pjcHDJsYa20xl5Ql
rW+dv1U877t0/qQlmcAA76V7AoUomfMZ4L2ET/1HDdmhkQO8dZf9xo5FILnNn+i9uT22Ij3d
V/AC791nprjXZptEBnpJbu/iKB5WEXrLx4NKqKZQN+FG2U4vWpKjuJR3nguHowseFVVQlCxb
Al2SqWx43lQ4F00rHYg6ILVqWUYei1awvt8/ar/uRVNLqMgBYBTcKakmF4sWRFP53MdjLhrw
exwzMjz9nZO66LFoBek79b95TEbj73mSGlrV/qNpySwyTg4qvUnfdyv9UdLweoA3t+1FCjw5
+ffC7j7+C/TkNW+At+5xjKs2yX2DB3brN0iVSk2r/B3gvZ+Q/BjtyaajAV6R1evn/h06LCL0
jmx/TJNWJPO7BktLXufXjKA6Cztv2JuLxumAdL+WOJ1mAEpziBVZvX5VUZuMhtQZXmQozc/f
tHnWijGL88TR55P26140UfAHjwNA/KWS7R9Zwr1D1+R3T9rNaJyqiVOhbhY5V0veRxdJOZOd
0dXHfDitO7MzIGbo7Wv56pvh/QyhP+YbQn8B3kv0qhXqWdeJA7yZ6jVnb9kRqwO8tyfTwnme
k51wB3gvlQp9wZacAh/grZ+QW3tqY+V+KQd4Bdk7nUL1I3hYQ+gdwX4uIuHZ0SGk8ZKZ6Fi0
IjfZz5V256IJeWZsHZ3pKdbsjPkiTWc692qbi8ZvMV07GqC/yjg5j06F1mg6n09n6LCGuBUN
FhKneuqXC/aQshPCKzSeKuFvn7Sb0TjPYVAW7KHDKOkS7hf3HT6mw+kNhchE1IQ1K20zN1v/
JnvfqvVXS9e01t8LvDmdF+OM2fmtA7yZ5dUilG3VP8CbE3rdD+mkmt4Ab07pPb2ekxm9J3bv
52Mu4Sma+4AH+KsTesMbQu95Q4gJVHV6F91TyYiKLJFzPhWz+JiMphYnds7uyAgp24kai1Yk
9E61GB/T0TBqD2Vlk5p1fKxr2vQuE3rDG+JWNJGbI33NR0N+ZHVFPs9/gb970G4GE5k5EGl+
O4IKlmwNWJTPwwuHmOlwemsYlnnAqslqOhSbuk68Kd7P0PtrWaY3wHuZXgxZZLNlA7yZ6Tk1
qkkWMMBbd9mqOgFOqqEN8OZ8nhWGZB/mAG/9hH7z9bdjUgJ1gFdwvQttZx32EHrPHqL5kQWo
5lzFkj0Ri4YYpF+MQ05FU0ukvpBqF5LkDEOsWdKbd3EATwXjjNqZHiApmRJnPYUXmUP89kH7
dS8aLMxdRRtCGPFm03m8RDrmQtp5LppQJCBDI6nq3CjP9ZZIO19NZExuDqjEjd5fMNzTNrx/
5kTGPiL3P//833/+v3/+73//4//81//9x9YDKqmatZcaZccWFryNF3Dw71A8rE0Kt6wx3QHe
XFH3G17aVu0A733MJBxxOcnAD/Dme1YtDZMV9QHenFHv+QbUAd77gjN2Up0UjRzgFQz8qs45
HDz0noMHVWSmEFYPi9Rs1XaJS7JdjKpORRM0z6o0c1ZUJekrvIbmYbuSvpmKRoqZdaeszelR
42R1pKzoLrmQV/l80n7d3RuLLgesHotaun1yxQTh9VD0VDR+tGjI1FfpFNqauXB81Yr7EV9V
1KfCIafgYflMDZyEZ5MfvuhPpOA/K9v6jYKHtYf/YbaMc4D3UgGm0jTbQnmANxM+9dM9mbYe
4M2Er5XsqMeB3Uzqo3qbS8kc2L1kL7Tdk8zowK6genxxAA8LD73jq0ClsjXnEp1BNJvQm7NV
+Ne6ul7I30wF46Stqh9YPVrAWro/j1cMQpucsfDHZDRSyLdFkH3bgZOlaFkzKHPJ9IaBx829
MWfhrCiVIG+TvESn+5LpTUXzZHqRb40hGa1JzcZFTA+v2nSnwvH7fFNtrZF/V/kp9faek1nE
9PbOTzBJaZAdhz7AmyleLcLZqvoB3kzxqGjWCWaA91I8lcI9eQkd4L27LFxq8mA7sFs/X69x
Bufe7Qd2Bck7nYP0s3d4ZOgd5wJ/+Bp0BGRhqD3ryKtL1HtO530+JqPBoiJ+TvVq7P/PsrwV
7wc0veienIpGwwScwlSiYuekt3lZcVusYBfNk8Mi4+bW1G7S0bcmnLmziipLxn3owr5kLhrw
W6WTISRRjd9ONp23ouu4IlyQvKlwoquESMwodsiyMuNzF/83yfshGofMWDr15FTkAd7OApiT
wigDvJnrheJvdiL6AO/leua3sZr8Dgd47y5rXDKz86wHeG9Kr1NplNzlAV7B9y6mZWzYY9gd
04JIhxoTQhc/RpIy0LTIr87OovmYjMapG2vUoDimMihbv9U1E9FnIxmPyWjEv+awYamta9Ok
QoAUXTIRfUH4bNhj3Nyb2hVjKoMat6zD0yrC99sn7WY04X7MTUJxNEhfdoJ4jWXyaRfHYzKa
6reEKoQxYoZZTes6ebV4871vlDesCgVFs2frC7y5e4v8FdaTz+AB3svxOIzps0MyT+zmsrxT
IkhOQw/w5mZavzzUrIzqAd76Ccm/FrNkp+gAr+BEp605fu4Oawy741dQn7JzSqytA2Tr5Gsk
n1XPx1TnosHITAChNsyOqa2ZkDE975ma3RirjIDoPIJqckImFi2gEPV04PbzMft1f2OEO6hq
yOhl2/NWaNM6vfvtY3YzGij6dPlxMqQEyeYXWOTAUi/o3eTeiF/tpEoY/ViyddsXve2IF9C7
b2nMUyn+ss+yvBd4L8sjLQbJDvgB3szyWsnq1h/YzSyvFc5mGgd4M8vjQtlupAHey/Ial9AD
zLG8A7yATFC7OH6HFYbdM48AENPegh71JDWqi2xK7HwSei4a5wXAXJWthwdxtgMMF+SK/LJ2
1gH2mN4baVGkE+beszMydU1t8JLoDSuMu3tTq2C1DgIk6b1ZQlvlvHA7F41zNmzQiDB+2pjk
rYuY3vmc+mN6c5gFBNVfBi3twTA5wPRmet8obBh1L39gk2myA7w5kSf+q88eRQd4M8Wj0ik7
SnaA9+5y60Uh6aQ2wJtJXi2Ylf8f4M2pPCq1JXd5gFeQvKti7fDDsHt+GIA1Cpto6GdVtvd6
Ccm7TOVNRROcQE25tSZZy941CaPrZN7k1hhVBqcSEqa92Y4pW5H+wtPK8+eD9uv21jxluIWM
sfV0onVFrbbKRa12KprgeKqtt8r+ArJkW8CqbB6dSYI+pjeHu7CxdDSzlssbRwrwzfH+Osf7
nmxeLybZ5vcDvJfqccgpJi9PA7y5Lw/8Z5Mt2h7gzfm8MJpLdl8O8Gaqp8VPhGT54ABvz+dJ
z3pHHOAVfXl6QfWGG4bd84/oVqMlD9Qkm4X2NV+dzpsMBkHFJMYWgCl7YuEK3mp2UU2biqYW
ET9/gfyLkp4kR75oiVDyFdUbXhi39waiabKHy3Vy0G8H1ZuKJqiekR9/5ASWIDmQtYzqXdwq
JjeHq4SSPdeqNd0zOTel/tOpHqWp3o0TI9kJt6IH7k+W9VNK3mhf2M15Rme8mh0KOcDbyaff
PbMDwC/w1j0Onb6s4fCB3bvH1Y8cyWq8PLFbP18HLai5xMKBXfBCwVMJamcDw6DD7pmnEEsF
E6ut9aRknC9aMUAhdpFhnIrGT8Lw+QtbOVRKZtFj0ZIU40VtbyoaLU4wGLmF+V7yt6Br7Eau
NF5s+HPc3BqTLgYduVfMDup8uZjfXDAh1sJVmz9r2CDPOpdIvNTTxPxjMhwq6HdP6LUpS3Yi
DP9INe2flV78Zik/w2yO8QDvpQCCpbdkbmeAN9M8J7+c9NUY4M00rxXOeqsO8GYy34plcyov
7NbP13ovDS2p5neAV2QYL5SbbRh02D2Djqr6fM9DQ02/5+uSFOOFT95cNM7aQIw6oL7GAXJM
b0WG8Uq4eS6Y0GCOZhgy1tqyskxfL9xsw57j5tY4OerVSXi4dLRsLntFL5BfBS8yjFPRhCcA
ABohhgBeMi8Ca9QJq14ks6fCoQKNhRphM7Ok4nkserO9NWxvv5wft6wd8gHeXErWwlmxgwHe
TPO4aJIBHNi9JE+lkCRHawZ4M5WnqK8nmfwTuzebZz3UyXLn7gCvIHkXcn42LCDsni6/n7nY
uaIxQ/JXRWsE8PjCnmMuGixRp6TuwYgfv1nNuCXFG2sXLG8qGi3OHjgylP5VaZLlxaIVObAr
eZfhAHFzb2pvlbT67vSetudYIu9Sr4SEpqKB58gOIlcRqJWy9sFr9Pzq2ZTLYzKcWir7CmVo
FTjZTlIntdvfLO/H6PmFRE+ywj3Am4lAZHCSL4sB3kz2esla2h3YvWTPQhEimfAY4M17HAJ9
2RGWA7yX7jUoIElZhAFeQfeuBkSGD4Tds+h4ytAyMZllE0e05NRCuZrNnIoG4xCuYr2R+Wmc
pRRLorGrqtpUNFqQKvgp3FVMa64JUtcIpFzSvWEDcXNvahdtIUVNZElTi2V079wQeS4aJ25W
obemCEqSzI/AIrfqenbre0yG48wtJsTUr0gNe9JAxRe95fz++oTIfjm/Jtl62QHeXNCjkOxK
lm0P8F6Kx1yoZ5trD/Dm4rx/LZqV8znAe79DtWIi2dGQF3jrJ2Qg/0uTuzzAK7JgV4J+wwbC
7onzA0F9quiGplf27b5E0O+ZVj47eqeiQX9Y0TqpAPtZlR4DXmPRcZHTm9wbp3fYe4jxGOfd
sZbQoiupl2EDcXdvKrUqVAUU0l16S6Re4GoKaSoaiH4baK1LByJMvk5hSfq4Qj3bnMf05gjH
+G9F7FKTj5oveuf0FpC87xkD1pKeD31hN1duxW+rycLoAG9mer1gdmJvgDczvVbU0o7KL/B2
pidZ6d0XdjPPi4p7sglzgFfwvHo+mdmG/UO7KcoP2JzhCZNq1g7FFy2I5krtZS6aJ5dAYed5
zv2TRiOLtJv7hUHW7N4Y1to7YtSh89rNC/oNL3leG/YPt/cGqLbWDGWvoh/iedZ4LpgY5m2i
HQwakCWNqn3VkkTrhXbz7N6IX49qNB1as6QVmy965/L+Os3br+jXsmWoAd6cy2O/eCe13gZ4
M8Oj0noyfz/Ae3e5db+4JYtZA7yZ4Wkkv9IqL47dzvAQ0pm8F3gBi7jS82vDAaLdtObAaC4K
/zqDfCZviWjzae7rYzKamLpu/nuSHqQ1qwj59Zm82b1p0BitgbFaUhfFF61geFcqL204QNzd
G0CpGklJM0uz7xV5SYTzcu1cNEHWmHoFNY7bRFrQbw3FO8/kzW6OkJEKhtdW0jo4sn9vhvfX
Gd63JPIM4jKcvNAf4M2pPI3x2fwQRoA39+VB8QM5r+cX4M2pPC3SslMOB3gz0esFOen2OMCb
qZ4VSp69B3ZFX96Fml8bDhDtnix/Nz/Vq9QelurZ8dQlcn6XqbzJaLCyYfPjFxGSqjerbNjk
4vSdiqYWC/8HM9XK2R6LNZm8S543/B9ubg1062H9QAbpIbU1PI9Oc18fk9FEKk/DWJlBwX87
6Yrtl6fyJjdHwJp0ADDKWjf8XW3YvkTND7MaTys6zP9kPT9L+3Ic4L30s0JhwuQnPMDbK8ma
dQsa4K27HCp9KklyN8DbO0ObSlbr5QXe+gk7xkxUUrdxgBe8WK50/dqwp2h3PANCoq8rAvRO
nPQM9DUrUnN6KoT3MRlMqOJ2RqLGUjGptjarintjLmQuGnXK5j89rBJK38mfgy5KzV2IvbRh
TnFzb5yhV78bCLaOSaWpRcJ+2M9VheaigWLcuLMwh0p2clBxkdgLw/kY8Fw4VPzN0qtp9+3J
NQzGkr8j/fyPEvZjzdYvDvBeHqB+0rTk7MAAb042cumWvbAd4M1sr/nXkuT0A7yZ02uRrE/c
AG9me2Hwl6t7H9gVycYLYb82/CnaHdOAMLDz97uIxAigZt/zS67EqhdH8FQ08UKq4O8k8mNY
ek72OBatIHt2cQJPRSOldQsNZ6euof2SVPbrX072hj3Fzb0x5mqkVrlB8r6+SNnvSsV5LprQ
YzZqrbJor8C5Rw3WyC7WU0fwx2Q4ztwovEMaqUjNepyXuUTKm+79BGU/bUnVtwHeywAkFIWS
rdIv7Jd9vv8PAAD//+xdQZLkNg78EYMEQJD4QB96/v+fBarEOeyG6BSXzR7b7XU49pCcqSyp
pCQIZN6pvKIM1vQu8FmVpzWJgBpqgA83DviNhVbhB/isyuuUugsK0OzlDd6h8ybefn3kQfRn
Nv2qzXVE1i7R8I56+20xcK6Tt+8Sm5KqcbHazF9Z+MllXapOPPD2W2OjiVv07XMVKwbebb5o
h5SYmb30EQjx8NpQ6AhWEnI66MHlFrMXljs2n4tscqrKjf2nE2fLYIp23pTfN7H2W2MT78n4
0filUYWdQNKajdqPzPuTrP0ErEgN8OGqXk3+/APrPRf4sN6zZB1NvLzAZ/Veo1QFdB8c4MNX
ObvIhN2H5PD5bY/pFPCZOMA7tN5sUmQkQvRnNv219V5Mqr+GscLEJls/0cn7d4lLSUrNmXBl
fzIJeny7o6lrfny7xOaV5ef3juTOaqARni7GZT1ReiMO4uG1IatExLllzuCeYpfSu62Efy6y
CT9mK3Gqnruilot5y55irvSW2LhoY6KmfnW0FgLDMH3Rj9L7v+dEvsHVD7TCurDHO7eagMbS
A3y4P0+SZNSF/gIfPpcPq0Mww2CAz36H6pIXnke7wEc/oeSaagX3GAO8QxNNPP36yILozwz6
M1m36vKuGjp8vc3Tb3Jmu8SmuLxRX8KmLrjA6+OL9hg3T2p5i9cmJoHDNi7c1hp6bbZMAk+9
XkYUxNNrQ1xrYfPNImqCt8nshWXSCrrEJieXQpJNw9HPd0hog57uaNCbTgIvXpxapWZpkXLD
YIvej6ff39vTT9DI2AE+fGpbU0fPHAf4sNaLyVS0O+8CH9Z6PamitdALfPY7bOTvbPCcaoAP
az3zrwUNs7nAG/QE291Jp7+BRxBEf+bOnzP5Y56oh0oCnYD2+PpNXV+W2ITri0jurTbODDZN
xaKv1nqL18a3qp2kM/dSO9afR5vCXWdab+RAPL02/of6vWbSW0bd2b/ev3mNTTgxa+nZtxQR
WQvOnZ/QeosXp7Lv9JQzkRp6DPVj+7JD65029mN/eqMP+gt8uKAnybfruLFfgA+LPE4GP8Iu
8Nmr3C1JQw0kLvDxgl4DzbIu7PFyXuvgBOQAb5F4k+PaEQPRH0Z0lLBbs15zYTiAaYuxn+pd
o+HnIpso55myhUeZWIdlxJeX8xavTS/WrPvNk7lX9Bhtx6Z2bvgyUiCeXpucNSbGrVTGbbV3
HNhOJd4Sm5B4NUZKGlXjBhqQnZB4ixenCvVqvpUgRh1LfyTe39zZD+yauLCHi3maRFFPugt8
uCkvJ8ngY+yNPVzK01QJ/CkP8OFSHsdsD1rKe4PP6rySk+sJUOdd4B1teRNfPxsxEPbMnN9a
kab+BtZi4DjnJl+/WSlvlU2JSKnGLTcWuCLx5aW8NTaUfI/KQiS+0TJwrCsW7ZAS/a756/ed
9vH02mRrrr65lEZwCsQeX79y3x+wRiZkHvVeODd1oQeaVG1LYrv39Vu9NjVyTCRmfWLsHpV5
/8iIDvoKXz+wMnW6JoW2Rm14Pm6QxN/mNcigDdQAn5XEFBP8YIXmjT0siMPuDHUavMBHr3FY
mPijGQ1dGejzV5nB8+0BPvoJLfsrHkzxvLA7JHG572S0kZthT8IMehQLWy2WWxc0Ga3vKRbW
fifwPxfZ+M+pNnW1UtWFPuw0uMd85q6O+2uRTE1WM2tptUUwGnavxaIdh9v9fvzdRmrGIzaS
mF0P9+p7lo62ZcaiHRpyYj6zxibMZ8ivjt9oUSvEnqWxaMe1mQxFrbFh3xS6Hi4tixTQk4QX
N5J/uiD+VzkNagbPU97YsxpAXp5t4AHtBT6s9TS1Aqb/DvBprWepoz/p3+jDWk9TVXSy5gIf
/YRdswseMMp7gHeovX7Xf+8v4RGeYU8iDVqyUkhN/UbMGdTXsWiH2muTl/ASG1du4f3GXSTa
stAkLtlSAL3Vrr8W2dQk70TfEBUMzhT5oh3Tr9TvXS1thGc8YiOJalFr7BfGCBSvseir5d4S
m1BuajFUJOGWDZ7IbfIa5DzRe0t0KJlYWFpqI2XYhGZtZ/Ej+P4Er8GOzo4N8GGtF2Yo4Ozq
AB/Wepx84wpKvRf2rNLjGCxXtPA40IfbGVrK4ODPhT1b02suLgVs/B3gDVpCaKLzRkiFPUkO
6H5xtdfWLLs+KmhVr+846JZb1fq5yMb3nk3Ut3hNCxN80L3FOXHmNbjGRhOHoQ5lLZLRkDTd
Eu4ysS3+fad9PGPzMjrwy9Kb8+lgQyNvmk9u9w40a2xeDjRNGrk4sm6GVZAPWNCs0aFEEvM3
zQrB1hCx6EfnbdJ532U2yIzduhf2sAyQxPAg5QU+LPZimgJsZx7g03LPNaah3q4DffY6q0s4
QZsJLvBZwSeaOjg1emE3SAq2yUt4xFTYk+yAniqLVa6qLBn8xmPRDrl3e+75ucgmlFsM81rt
VRTu0twj92anuEtsajJqhVpuRNwJeyz7oh3nnqSTst5IqXjEhlPuVJmaslGFkwl3GLES30rx
z0U2OWnmFpMk2QozSCdW7ZB7eVJBXqJDyXcUGs0ctRGaVkM/ESIb5N5xx8GSfDOHvlrf4LMv
/0jcamA5aoDPirywEWxg9+8be/QaV4kWC/AbHODDDbVxkACe0A/w0U8o2XUv2K9+Ybd06U3G
CUY+hT3LDmnVKmnVoh1VrLwlprXobbvR5yKbsCxpnUscRYuBzri+aI+j9KSet8SGUrMXD4ng
dbDVIhZtKRlNthIjn+Ihm+x0pGqtzdUEOm69ReDRJDtkjY1LNeJWexfuORcwpiZW7TiGngwo
r9GJWePwG8w5N/9dov2tPwPKOwTed/kNagYLUQN8Vudx8x8/+Jh4Yw+rPEv+XEGdpd/gwzrP
L5s/oUCd9wYf1nk1wlTQ8ak3+OgnZKPII8Nk0Ru7Q+dNMuJspFPYs9wQVbLCqubPeUZ13o6B
8FLrROctsXHJVqLM0f1NWDOY5xCLNrB5JUPfvXyX2FBSzv76tZKbEGwStCMHhfxH9Vd32sdT
Nrlm13hE5rcxaF0ci7YU8v7yTnvIJhQbuWANbwQuaHruLp3HdwPXvxbplOR7CZfg3KOHEo04
9UU/Ou//1nmnvQYp9QpWKAb4cCGvJrDl5g09LO84+QMZnG+4wIflHSUuYNfbAJ8v4+E1vOMF
vMbgcMgAf3UJb8RS2JOsgKjGdYlcR3+stw5q1S0Tg/MS3hKbqMYVq9VypgZa+56o4C2RicSQ
KKywZCpWUGW3JTFkWsEboRQP2WTXQFIlR9g0nk2zpb9QJh15S2xcoxVrFH2s5A9GQuN/v76C
t0QnXKR98+mMcrMMNn/+VPD+xhaDaql3MBN2gM8KPIlRAPQs+QIfbsfLSdBU9gE+XsPrqAwd
4MMir6dS0AGWC3y2htctkYJHNAO8Q+r1u+27v4FHKoU9iQrgpMy1NM7GXRtcxduSDlcn7m9L
bKIg11zt+caTa8YTQ3Zcm86TdrwlNpRqV61Se2nSwHMB2tTgf5uY+/tO+3jKJpOWEK/+TwXd
e/bkEM6reEtsXlU8I+tsuWW083OT1ivlrsT6a5FOjKcT117Nd0h4OPNa6PqfrvX4K3wGwXip
LcFS22ZCzjv6KaGjPxf4cIEx5idAc8YBPq4/GY3efGOPXuMS7jdChrq8XOizV5liF4vuMi7w
0U9o0hLs+j/AO/RnnpztjcgMe5Jj0BM1alq6GrUO+qLEoh36s01UwRKbONeKjie1YgyX+hcP
w/6n1jg52ltio37bUAy2kMY+Gqs1xqId1bmZqd9IzHjERhJX3+qw9GyE9inFoi3HrhOXlyU2
4fJStZqoqIUd5kmXF5m5vCzR4cTF2VBrmQ3ujklrrsx/uv78V9n6EaMFxwt8VgrU2IGCpyxv
7GG55ypYCqr33uDTgq/hbjQX+Lior6jVyxt7VuxxuLdgj8QLu6XUeHvYZ/lKzYj/80TqZd9x
uMiLcLTOWI3BF+0oztX7oIlFNq7aSo5wYnNt1MBnWCzaIvVu6z+LbNSvTWO/6E2Y0fZZ3XJt
KNut1BtsPp6xkUSdRWrxf7qBqRmxaEdtrt5aCi2ycdEWcb4uw3NuGfdv3iFc5XbD92uRDSf/
imIKqWT/5YBFbV/0o/Q2Kb3zfn6uOcDd1gU+fKasyfeE6JnyG3xY5EnSjkbCXOCzIo/Vrxzq
dnaBDwv56E8Di/ADfPYq56L+CiLwSxzoDXJC6PZU2XIZcuJZUod/sppNtZRIhUA9/faYvNzW
WhbZlAiVUW4uKsi0oYdjW45y2m3c269FNr5BaC7ETXOlZmAsTCzaUtWbbCrKkBMP4yBYInOk
q1QDd0m8pbuTqN1mwiyyCU8/iniL6nJcMjjqEqt20Mm36XWLdMKvjaKRmHI0mIBb7MUclR+t
9wd5+sHz6wN8WAzEuwbN7bzAhyWf+V9acVe/AB+WfI1S6QU84xro46LPKlgdHeDTos+fdxl0
R7jAO6p77fYg1zINWfHEp7/7S0hMKBLawpAW9fXbEs5WJ5JviU3xD9Y7qcsv6Yrnru4IzpvY
OC+yUX+lRlnPGRXO4FyC7skzm/j6DTYfz9i4esviu4oq1riA14b3BBbTbHOxxMbFW5MaW4tS
iRgTsHmPHH9Jsvmd9pANJXKJ2CVCYcQy2uRJS7+bH8X3zbZ+WVELqQt8+FyPH3j6XuCzb/+w
6gNPjl7Qo1e4+l+J/oQv7NlvTzWZgfO2A3z0E0qxxA3UQgO8Q93dTwT7RRoK4ll0QmSIUhGl
YqgB0KaJ4Ho7RPu5yKak+EO5SowFF9C6xhdtyd69HxNZZEPxy5PwoGZx7Y3ao9gWY+D7keDB
5uMpm9wbxTFqJYOtXnaMvHC5HQhe5JKTsmkVLeryW+GIjh2VY38GTCrHS3QiV1WllBYTLx0e
CNalDeuPuPszLP16YVTjvcGHD2+r//jBWNsBPqzxLJUOVkMH+LDOs9QKeHg7wMeVXkcPbwf4
sNLrKUY1QaX3Bm+p4016p2SoiWepCdqlZelVMteGHqhtMaPW21rR5yKbGAju1ekYW0fdv/fM
A0+8XxbJhPeLcrZC+VVe+UO8Xwabj6dssmbqzOFQWEGToU3eL0x/eaM9ZBOTvb4Jpl7M9VHH
4zl21Fgn3i+LdEqqGjEjuRQpuB3mWlXyR+p9q6sfpww+5i/s4SqeJAJnzy7sYX3HLjfAoeUB
Pl7HywUcFh3g85U8dFryjT1ex1MGh1MH+KvreHVIiIfhHN0f6Tmbv3sbXMbbckg7K+MtkYmK
XM7C3f9sMjhi4OvLeEtsKFmJTDwjdVUEbiV80RZDkZm6q0NAPMzm0GZRX82+nUBtCvOOU81y
O7PwuUgmZJoIU/QDiKF9zpvE3bSOt0Qn+hRqiVPaSpHRg9bxlgrGP+LuzzD2a+ipzQAfruO1
5JtasCPvAh/uyMuJDXxlDvBZnRdugmi1doAP67zuj3h0VvICn1V6REkMnFYe4K+u4+mQEw/j
Oao18uuca2MwAmJbPMdk2naJzcvYz99WYXXB/uL6Ywp5S2yikGeUTbS9ciCOFvLu4zkGm4+n
bLLkEmEwTL0pXMjbccg5iWFbZPM29mtdc8kxtXA2nmNWyFuiE4U8zewvI6bYX/yrC3lfYuxX
0Im9LbN620ZDzlv7SUWzOS7wWQVKLohQB/o39vg5sho4SD3AR6/xy6yP4TnlgT5eTS7gPOqF
Pfr5LDYOFSz+DPCGx4rcBry7KmhD4zxJD+iJs7qs9Xdpi8AKcB5kh3+Sv+YmFaAlNiVJWChW
ZWJB/cli0Q79OZsHWWKjKfoFpRFVUzXs2ugeK7yJsd9g8/GMTXj01V6paosAXWyn44u2hIiU
yQjwEpswbskx6SXMqgoPhGyye7k19lukEx59xkWKcRUDR4/4ZwR4n877NmM/1Cb5jT0rA5ST
v/LAD3iBD5cbJVkFrSbe2NNir6cmaN7jQB+W9C1FkQXU9G/wWbnnOl3A1qcLu0FQ8MxwrQ9B
8SQ+oKccPsH+kNduBo409S29XC72JsXGJTau27TWaHzi5iL2ayNN/6fYOHkDL7HRVKhxcRHe
ayHwZtM9DilTa78+9MQTNuHS1zO7cvU/u6Jhi4sDpv/N5t7FeZFNuDhb9916JzUm8Hm/ycWZ
dHKwvESHE2l4YuZerDHYlR+LfsTeHrF33tuvEdiWP8BnFUAlf16Ak0oDfFznxVQlLPQCfFbp
+TY0SQWHJC/w4eYBdf0BOvoP8NmrnCnsNNBWm4HeUdijyXGfDT3xLLGjq2gvrZQIh8D0RCza
ovUmx31LbKIXSkk4Syu9ZnQUeK0X6r+1nk203hIbTVo7xRxNzrmDg+e65dB/7u1nQ048C4Xw
x0lYvbh+bQ08+vBFOw6WeXawvMQmp6oS/s3MrqoIK7rGoh1sbHKuvMSGXicPqqWTSIfT/NYq
AD9S7w+y9qsK2tIN8OHKXk0dzu66wIcVnyVDj8IH+LDia2GXhc4sD/Th6xyN/GhqxwU+rfli
zBf1pxnoLc2E95qvjHiI8iy6o3apNSouhRhsj9xk7icTzbfGpsR8TlNmiiNQRs39tmQezw5z
19j4fotLKcrl5VeIKVjdcjQ9NfcrIx7iEZt4lJDm2qpJkYbGQ2wx93vd2PM77SEbl2+WS+6R
E8OdwROxvCfCeebut0bH9ZtvlfyyFPLnPehOTT8pbTsGR867+xGhQ2gX+HAnF6eG9sMN8OGO
PUnwAekbe/Qavzz7OlilH+Cz36BqauDr+QU9+umEMpwbd2F3iLvJTHAZgRDlWYRCa1x8lyEd
PoI6YO23Rias/UTMBUSm0sDWtli0Q9tNZoLX2MRMsD8auqpxVnRX64s2yIfZTHAZcRAP2eSu
pFLM5O22d87cL0+6BNbYxHhvuNeo/3ScDnhAcsDcb41O1LStdX/Gmz6YsPox99uh7b7N3A98
QF7Yw2e3NfmDDz27fYMPCzxLBe12GuCzEq/m5G9B7Mc8wGe/w0bJXwngd3iBD8s8Dk0Bmr9c
4C1VvPveqTJiIMqz4ATtzaUECfkfDm7ffdGOUIup0lti81J6ylmcVGYDy6yblN5kJHiNDaXO
ro1iSNNVBajCfdEWMTFTeiMG4iGbrEVyd6mXBYwI2mTtl9tf3mgPyYRkq8K9C5mF8TEq9PZM
ZNyf3K7RiWibKo1KN+EGpxmulSR/hN53W/t18LRmgA8X8cQ3qxnUeBf4sMbj1Dt6WnuBj5fx
cgdNVQb4cBlPUq1omN0FPl7KM/Q7HOCvLuaNMIjyMKijF+mZqJI10BNvm8Pf/TDkGhuXa8Jq
NUYh/b+oU9mODrB5NW+JTZj1VX+CdaMoUMJBHVtc5GYab6RBPGTjWihHwIVV1xKwyNth8Tfz
b15j8/ZvjhRhEtdTYGbkAYu/NTpRzYuQZ+YuUhiOrP6x+Nsg8r7L4k8baFE7wIfreZr8xYTW
897gw515OUlGLVYu8PF6XgcdDi7s4WqewGbiF/awznNxmUE1P8BfXcsbWRDlYUyHhsTjOLWt
oL3KLnu/WS1viU2U5Rr7yzfmVR7kdGxxcp7V8pbYUOpEImISfMDqeyzaISUm9n5lREE8ZJOF
VGsvmYuhgZ977P2mxbwlNu9iXmRUZ665gb6Ym4p5M3u/NTrh1Of6zkV45yZgXt4/1d6P/vb2
fo+KKmA5ZcMjcoMq/jbTQUI18QU+q4nJNRpsOXj4BqslMdhOfmHPXl0XDL6LQQsPA332+nJO
GfYZusBHP6HvEJIaOCE/wDsUMd3NvrpOGfkZ5VGqQU/ZsqvHxjWM4LAbt29pL3P1eu84uEgn
1WLUuzXRIuieKu3o0C0vBX6nU5bY1CivORXpRoTm+tY91TWye2/LMgI0HrGxV4BGo0ji8/0K
xsa2DI1PTWjW2PiLxX82JM1FfpzWo6XPLXbkPHEcXKNDyTpHh6nfb2wN9HpNa8Hrf7ok/nc5
DmZUDFzgs1rgdTgM3o5v7GG9F0YQ4MHHAB9WfIVTKWB56Df6/FVGDYfe2KOfT0tJuYJVnAHe
ofdsctI9QjTKo2SDltiVCvlrWCPNDiw6L04j/rcRTZscda/RSbVqjzG6XjMpXMnZUgK9VUi/
Ftlwspxd7HV5xeKibQi2QyH50/2vbrWPZ2zM7zRtxUVfFRd8GBvbcqe53rs7OvhcZOPKjWOQ
X52TEhr8nvf0muaJ59EanRgQ8g2L/0elGTwjtTYx/qP3/gTTQQU7gS7sYQEQrjeoRrnAh4Ue
+1YU9aK7wIcLtxbxZehZ00Cfvc5NU2voR7zAZ0t7KskUzFQc4A1qQmhy2D3yKsqj9I0er6xO
nXOpGR2p71veWKXe9mh+rtJJPZfuOiJiKzJ4dh+Lvrq0t8QmHrE5ZkZrya7ysQ3uttLeXTHs
96328YyNb2uFWEopPXcBz/5001DvJLh4jU30J1b2f3Nh6q73zs4oT/xnluiUsKCoRWrr6tcH
rYnbz+jKLqn3XaaDaAvrhT3c2ChJKppdfIEPKz5LndARyQt8+qi+Je2o4dBAn73OZnFvgR/x
Ap8t7vWexMCGhwHeovgmNnAjtKI8iuBoqTdTyiSi/jJGi3tbPLNrn3iFrNFxNkWLUWYxOEQ8
7TgBKG3i/bvGRhLnFtHFViWDI0ayJdmPpmXkkVnxiIwmUeZiORexDJrIx6IdCqlOxliW2Lh0
a1obUxauQuBxk6/aESgybW9cohNF8fBl70qs/tr80qL4j+D7VsPB6LFFy2YX+Ozrv0jKWcCC
zwU+K/NEUm2gEB3go1e55NJTgys4A324sVb9AQLOKQ3w0U/InRNX8KR+gDcoCZ65/Y68ivIk
RaCl7PJOI0iAXU5gvy1ftMPDZTrFssQmplgoq3BvGbWt3ORHU+/qYL8WuZA/YP0rYhffuWQ4
32HPmMStYv19n308YxMny520Ww8DQrCqx3t8FKfOg0tsoqpn2S8Mu5pyJY66Su+p6pVJAXmJ
TiQnZpesbK13PFr7HznC8q8xHuSOSr03+KzU45aKob5VF/iw1LPEymBF7wIflnq5JepoeupA
n/0WG6Xe0ISOC3xW6mXfR6C5cQO8o12P7g/WaMRU0LOYihbCiM04w7FxseiLpd4am/fAsknX
zK6LYbG3o9pqE7G3xob8tqlV1a9NEwGrrZtGfF+JxPM77eMZm/AmFxcSrXSRCj4j9xiah/r/
qzvtIZuQbc1/L06EqRawv23TwDJN3AfX6JTXqUgpfnGcFDgZt+ro9KP2vtl9sDS0XnaBD1f0
aioER4i8wYdlnm9CFZzIGuDDMo9aqlnhZNs3+rjM44L6+lzgwxU9S77/BWXeBd4h88r9aCSN
xAp6EiPgeyH2vXyrJJKtYMKo7XHsk9tusM9FNv7iMY2J1ZjFRQePYrZsi8y7N4VbY0NRTG+a
i/SIekFlXtsytjqp6dEIrHjEJmp64uox9hOKFsE2jZiw3A9lrLEJwSYuvqlRjvwa2H9wS8GV
70qUvxbpRH3Ost/DZhbBkWhR72cId4PM+y7/wV7AN9gAn1V7EiPrYNLEAB9u08uJDfUbusCH
1R6Hhxz4HrzAZ7/D3lJXsLg8wGe1XtFUMnhKP8BbSnr3Yxk0MivoSZKApt44m5hv5eNoDSzp
belqU5mU9JbYuGwTK66MXB/lnEH/mERbzm9v29p+LbKJAcfSVWvrrRgc1bolR5f6pHg8Mise
seHU40bzV4aQEFgDi0U72My03hIbV22+T29cI7imC9hBmTcJ8duL82uRjm+SWqnCMaFV0Dl8
X/NPlHr8FRaE4Pt2x5v2b231V8CQrgE+XGy01NDTiAE+Lz8Lavj3wp69xk1DT6IDt3vMjh+Z
OYo/1cDI+gE+e4Xzuy0V7b58gbdIz7v6gguCEaVBj/INeuJeq1TyTZqg1WdftMPsTyeuxIt0
kktP1lp7bozO0MaiLdrzbur01yKbOLWvrWXN0nxrgNWA98R3E936i/y+1T6esbGkncz3scqV
0GQ+2zRRMTH7W2PjKrJXEf/lcOMIO0G1544Q5nJr+vlrkQ6nWqlJFjW/18DiTiz6J4rPf5XZ
X+more4FPqsFarTHgLvuN/aw1qsxKQZqvRf2tNajVFDv9d/o83oPNZ4b4KOf0LQmQyMbBnjH
QewkbIxGpAY9yjlorimohf1LJ0WLc21T+2CdVIDW6CRhsyIWMxYwnbTjPKK023mEX4tsNFGu
pWW/e16VIFDv0Z6B4Pu8ExqRGo/YWJJeLZswlcqo19+O5/dc7i2RceGmFmf9xuKcwJb2vKcZ
Uibezmt0OIoO8ZupXVXhOvBaIeVH7v0JXn/Ys/GFPHycrKkWVINe4MMaT5KivjQDfFjHSwz4
ggMYv9GHlXxPKuDh5gAfruqZRFc12oJ5oXfoPJ60D46cCHqUemEpq9KrGtYMLUbbllTZIrcp
fZ+rdCJmU0ozycEJ1Xm6g43Vydt3iU3zr1nUxZE0jlcwOq29Q0u8YvTmt9rHMzaawsOGa+He
q+8s0Crllvzifm8fvsYmp2ocYcwxkKQNPGeKVVvOlCdjIkt0yF+XMYTmN1tTNGElFv0IvU1C
77uc/rKBiu+NPa4FekUHRi7wYc1nqRu4BR/g05ovIu3R8e+BPnud9WUqj4Zpv8GHNZ9fuyJo
t81Ab9F89+kKNLIi6FHyRU+SK1ur1JVBq5FYtKF+5JpvUnJZoxPuHKW3rpYVdIssW7w5Qmfe
v4eXyGhSYquqWlRbxR7NsWiL5Ju0EY6oiKdsqmu+3MyKojnquqWPhPi2Jv65yCbEmwskLpV8
t4TmTG+SfEL3qdlrdCj5jdaKZfZ/BZ0b9UfHj+T7v0dGTnv9Rfsn2gp3gQ8363HKCibjDPBZ
ASCSBD3AfWOPXuOSuSVq6CDGQJ/9DrUlM7BpdICPfkLhOMIEzzkGeEfD3mwueKRE0BPr/pai
0ayb+r/cQOt+X7TFz1knGm+JTTi5+O36yiKIWuVJ+5dmd1XKX4ts/PFFZjmC2lgbYWx80Y7p
Ct+V/NWd9vGUjYXXdiktSmHgAygW7SiEzTpDl9iE/QsTZyWSSG2D54K3eP3RpDV0iU7Utv1V
6Rskv9G0osMia82UPyLvzzD7qx20VR/gwwe5NQaYwHPcF/aw0rNU0GLUAJ/WepETi37EgT6u
9bQXXOsF+KzWI0kd/RIHeIOeYJ3MBY98CHoWqWAlq0RjdqSnoUWjHW67RWcGbEtsXLYR917i
3LMXMFwlFm3p1buP0FpjQ6n7VjDHzExhtGHeF22ZzZjNBY98iEdsOPVX3kVx5cVoHyVvmUCn
MskFXGPjqo26mYVLFsWABqr1tghxnoygL9EpcSTdsr3m0HtDN0lr5ckfrfetVn+UTMBAggE+
XNCTxKir0gAflnm+BxXUEPMCn5Z5nHxDDcu8N/qwzDPfQYCF2wE+XNKzpGjz1AB/dUlvRETQ
s/CO0sKZ1iL4qYEzuJtKenorWj8X2cQpg0uiLMRhXQiX9HawmZb0ltiw77BETFou1EF7at6S
qzJ3+hsBEQ/JOJ5ZYk8hHewW9kU7ZNG0orfEJmpz4sJIS6PWrWN32omK3hKdV4trWFRJ603A
mNbVFtcflfdnOP0ZOAZ/YQ/X81rKjPYPXODDTXph3QfWRAf4sNQT/1vhxOCBPvsttoibQs1M
LvDhip7vdAp4SD/AX1zR4xEQwc/COyx6MIpmq8TgVt4X7aiBVb3vlV9jE3ECzXopPVPODP4O
NyW13UaR/FpkQ6kXyq4oKjWXe+BJiy/64ooej3yIR2w4+Y5Cq5K/NvzKo8p1S31yltS2xuaV
1FbFdxX+ACqgG/omqTdL411jE8G6WiMkhsQaOBrti/6RUu9LnP5Qw4stVhd/Z68/3w3iXn8B
PitBKaea0fmBC3z8UFkF7c67wGevctOesoHnbb/Rh6vKNRGBacYDfPY6Z6n+1EaHwAd6w8Nl
NifCI76CH2UK9BSvndy5NqlosGD3H9cOFTrxgFmkk4R7sVrIuDMd9YB5WQzeaYMlNi72u/Yi
QsrS4SP/HaMIdFs9/X2nfTwjYynqpr7bEfX9AZhVaHv8mUu9q9B9LrLJqVWhLpFk45oanK/M
e/wYy2ROZI3OK1OAxUrlahlMsVk1g/3TVei/yvKPGtgJP8BnxYByTDDheXcBPlx3lHhKo8PB
b/Bh0dcyrkt/ow+Le4tiJ1hnucCHRR/VlAltVRvoHaKP7vrV/FU8ciz4UbhAS71pc52Ua0Mr
KLFoy+BIuaPzuUoncrG0+ZtY/Q0GJj+s5mI9mA5eY6NJX5OnTNIN3GPEmi2i7y/vtI9nZCy5
FM8uXruGzTNq/LdmOfLA+G+NTfg8Nyb/x/9TFLSiPeDzvEaH/Xu2XHN5TY10VPStvWB/RN+f
YPxnCr7ABvisCqiUCCyBX9jjWq8wOu9wgQ8r+uq6ozVQSA304V6CnnzDDH7EC3z2OpdwOUYH
wS/wlvLe5ORvpEbwowwMS/50Fw77sgrasb3W7BB6bXLGvMYmpFGV8N31W7egQm+HNip2m433
a5FNS/4My72LXxkBY5Dblmi8qfEfj8yIR2TCw6+T/69EdQ+0UPJFOwI9qE2qe0tscvKbV6o2
Lp27wQPCa6ey/2P8dz+ftEaHUlX23RHXWmoGO1dj0Y/Q2yT0vsv4r6A/xQE+XN2rqQt4O76x
Z3WA5pTRdOMBPq334sAHNnu+0MevchH0I17gw7U9a5EWg/rqXOivPtAduRH8KAWjRzWscs/m
CgzsXItFW7yr2/345iKdcJez7lvR7AvBqIWyxV0uZOb9i3iJjaZeqyvJViq5vEBbPnf0sUyd
/3gERzxko73n2sSsu4KFS5U7qmHcJ5pviU14+MVpbm2u91yTo85/uiVAuP3lrfaQDqUYrI/h
q9qJ0dSsxcfAj+b7buc/+Ij0hT3c0MWpVfT48QIfbtyTJApWpAb46DV++bt0AlPHfqMPq2WO
zCrUDeYNPvoJRXqqBfwSB3iDkJiNCfNIjeBnqREhkmvzp3vrmbAtVCzawGbmBrPGJoxdLEJo
ardSFO3aKxtmUcsrvuvuzbvEhlPJoiX7vUMqYKNbLNpxSHjbg/j7Tvt4ysZqTKLmbsYG+iHH
oh0i77bz4XORTbjB+M4twuh8V4H2u+Y93tvldrP3a5FOSa00qaStkG+O0B9O+znB3SDyvsv5
T8GT+gt7+AS3phhlAo9w3+DDWi+Ot8BPOMCntV71fRjYlvkbffZbbBxzF6BivsD/xyf8DwAA
AP//7H1BsiU3juSJhgYQIEFeQGaT/xjds5jFdC1m7m8DvBfMhdqC6cHi509JX2al2nik0iPi
BZ0g4L6i9UqiCp7cDPAGPTGdEx5xEfIsYKErixBbdVkBDrPFRTvOcG8na38ssgnDZuauzTQ3
MbDkusflufG9Uccam5x6Ew2XjmzCaI077ehdnc8Jj7SIR2wk+XfEqcTRZ7YCzwnvYCNtMie8
xCbamHspKhIWNwq27fhVe0Y0fvmqPaQTRe3WumZXroIGQn97wvwlnf/C5A0dy7jAh0t6mnpG
Dagv8GGZ53tQQj3rLvBpmRcNuOgJ3UAfLunl0L9oSe8NPizzejIBhegAf3ZJbwRGyMMwj5aZ
oyezdAbPBrc5/01KektsoqRnRN3YGlwT3lPRe5nZ3S29S2T8C5uLkIrFHC44LyNb2Eyd/2TE
RTxk03Nt/j/uLvQ6djK4yfkvl8lMxhIb12v+4SHpEYVTUZfSXRW9mcpbosPJqJn//v0rUPxb
gFb0vjN6N6i8r3P+AxtbBvhwTa8m1NP+BT0rUQolJXgm4w0+LfTCxgC2C7nQh+t5NTVBj5cv
8GGhp4kIfA8H+LPreSMtQp4meeRWc83+/2gy96YkjzJzY1tiExbPxapLvZZ7BY13d1k8zxxX
lthk/7zGql6oCwmhXVNbTjun9bwRFvGITVj4sRYrvboKBxutN/n+iU68fZbYRGWuULX8miVW
cM9He5KG+XY062ORTsRTq5VG7EIPnb5dzbT+aqV3Tsf9n3/917/+37/+63//x//4z//1f//j
6BKFvZCnKzhg7WbD53iDBv8K60OtlgoY0Hlhz+rvTKmhKStv7GEFzik8EUAF/gaffcIWk4Zo
PMgFPnoPK/VEBroIDfDZp+wLur9aqLvlQG/4rHCbVMBGkIc8y77gklvLwtpctqLGF1u8qovc
sfmxyMa3OtlqZyOWQqCPuG5JGuZ2m9f2scimxe7IavP9RKtimAJvW3ZHmeSunPfzTfvjGRtO
xL35hoLCBgd1Wko75jAzlUn35CIb8VctGh2Kb/jA3pq4aIsAvztw+Vhkk9/dDmQx4K1o+MZi
t8NXC/Dfq9T6hZ6HapLUwGOCAT6r9zQSOEG998Ye1nvVNTAYTDjAZ59xywk9CbqwR+9g6cX/
m5hgvrBnn3BuNcEuHj/RO7ReuT9W15Hkoc+yL1yFVhbR3nsBv/Jx0Q6tN5lfWGXTqPrviXIB
l1/ZEkrCrw3ozfK7RqWlzFUyt2KlVXCEyS/aIo0mQk9HjMcjNi+hZ5ms+FPP4Gu2Segx3xf1
V9nk0sT8DyaxAqZQ+kU7Kq1y6030scgmJ+PKViNiRTocz/09JbNL6J09b22NEil4ljnAhxVe
TtLADccbe1jhSSoCZ+m9wUefcZGXvTIooS7w0XtoFEOQ4N9wgA+3yIbtC8N5NRd6R/Mk3Z+p
60jK0Gf5Beoqr9eau69YDT3p3GN60++tSNbYaCqRLNGktF7R4I+4aIfQu+13+Fhk01OWpq71
qPbMYEubX7Qjry2Xe38lHUkZj9iE4Yt19XesqD8b0G2c9hh0zyytV+mY74tIaqvNfB1E6bQ9
Nb376vEanTD7ZCuqJgbboq06hH5Lvd/E6bC1mjSDPZQDfLiHUiMxD+2ifIMPa76eKmjvcGHP
Kj7XwaWB7QwDfPYMV1ypV3Awb4APn+EW820t+JAv8Ba9d58roSMkQ59FF0i30sl/yI0YzCV3
vbclte7WFvDHMpteeiNzmUS5g6YkftGWmWialFuW2EQ4YNhlx1RisYqe4O5IFHS9NynsjZCM
R2xCueUwWegszbdo2M97k97z/+6vXrXHdMxVV+cSmXXUwJ0SLQ6Y/Fm+TtKT1+hwKsK1S3fl
2gU9k/KLvvXev6v3DrschkF1Y7AmNcBnNR5rQktSF/ZwvUeTFTBoYICPPuPcKClW7XhDj94/
IUkM/vUu7NlTZbPY/WK/kAHecWab78MkdCRj6LOcjy5WjKl213aguuNNjjezat4Sm5zIFzWh
StzEBOvPi4s2sLFbV5WPRTYuO3t0snX/xnIHT1lkTygx00TdjWSMR2xcp4lEqYiVhRkckYmr
dtApk3PbVTpNfVvkgsg3FBk8VI+rPrXf8GORTrQOqsavp5F2eLZsrd/wW919vb1heO6CL+0b
elbgiSUS0IBtgA9LvJ4K2DN9YQ8LvJJaRWdZLvBhkUdJBCyRDfBZmVdaQpu/LuwOkTdJj9CR
haHPkj06M3Vfpojr64/HRN6WMehJesQaG9drZK1ko1p6LaBDa6ItvXl5cmS7xEbCJqn7/wqH
TyNakLQthje3I+o/37Q/nrEJuWaWi4SBphJok0yLo7Z/bmezyZHtKh0jYnZOJU6iYV/DHeF0
972GH4t0OGX1rRGRdFIydA56be3/Fnlf6GsYLru+S0DjF97gwyW8kjiDfe8DfLyIlwXMWhrg
sxrPLHpKwHt4gY8X8gj9Gw7w8VKeGXicMcA7WtluG3J87R1hGPosoaDnSlJdEtUiHe0k32E2
x+U2svfHIpucOCIea9EInW3YrzBvifaYl/KW2IRHUmkk1CoTqiN0i2bNWe+HunVkYTxiE5Z+
/oIR+46MSu9wY96WEYw6UXmrdBo131NElV4JDLveVcqzyUHtEh0XbN1cf+daO5x2/V3K++v6
Gmrxrzj4SXlBzwo9pTDaBD/gF/hwPx4l39ijMxhv8OFiXk2GFm4G+OxT7jWxgPnSb+zhUp6l
IuAAxgDvKObdft598R05GPosnKCH2TMVJlMWdPyx7xBGtUyapFbZ1Kh/9a7hlIy6V2/qx5uc
oi2xkejVLS5YWy9+r9ATW9vS4T87sR0xGI/YRDFPpZNrcHJZBPrmbTqxnZkaLtMJ+z/pLDVT
BfNwNpkaur781bv2kA6/6g0vs5uqFZZ5a45qv7vME1jmPekyB/vLd6wT26ZCvsDQT7EPw4U9
XGWM8QlwUGCAj4vPzGCc5Bt79gmHR19Bm0Ev8NE7WKsmX6cw6TDAZ5+x9I4Xan+id8jPiaGf
joAOfRjQYWImXaPUCB7wxUVbGgYnmmCJjabIdi7dl1BmtJAVF21g48v9vSRYYtOTcCssrUlW
0PTAr/l0m5cRz/GIzNvmhWp3JdhzQ8vZe/z8buODfyyz0UxdOHNW7Wjg6JYXLfphf/WiPWST
UyRU12hONetgF1Re7Ez93bXnP8rPj3PHxNQAn5V7JZq5Caw1XuDDcq8ksPX5DT37hJv/SA1s
uxzgs2Iv4kYUDHgZ4MNir2myDN7En+gNguKVbHC3Bo+MDn2WahGDISLKnamAq5ZftKVx8Dbw
68ciG02swv5CSMm+xKPuzVuO+2fuzWtsWupkTTTsIFEDqQPmzToSOh6RCd1GjTTy2Oywpx/J
xDpykY1U13k10p1zhfvsduxKs9zukT4W2eToKzHhatm/VmDZNC/2lXyLvS/39LMe7R2gw8sF
PnyiXJN/UMHhkAt8WOXFoo4Gh1/go0+5iKashrr6vcFH76GVlloH+wYG+PBT5pxgU78LvKOo
1yfOzSMJQp+ldPhC1UxykxapbKjHy46UjqqTM+UlNurKSNtrErjWDM4y6p4T8n7rivKxyKYn
MwmZ17I0Ah1r4qIdrYOTRGQdSRCP2Lw8/cLhpfiGQitYOtrm6TepHy/SaTVbUW7+y9EMJjzH
VTtO/G+rlB+LdCLduL/SxBs5JVSGf9s3b5N6X+bpJ9hH/8Ieruq1hNaYX9DDKqCn1kBHxAE+
q/WUUy1g0/kAn63qWcOTYgb49DF9T9zB4vdP9I6q3sTRr4w4iPIs2cK38c1XrW7hTYZRChvA
HVU9utOuPxbZxNbEBYVIbWRo8OAWy+P3HvRmAV4j0/3j6lcUarlkAVuS+5Yg+KmhXxlpEI/Y
hGwLmadRP5YK5m8fMHBepWMxWFXJv4/dty2wod+WaeDbcvjHIh3XbeTP3NhfNt9aoAfsa82q
32Lvqw39CprSdYEP9+lJygJ+vQf4rAAIlz4Dj5YH+OhTDp8+AQ8bLuzROyi5JKrguegAH/0b
lu6bGwLbfgd4R0FvYutXRhBEeWbO32MQ2D/wUZWAE++3CNY6seFYY5NdrhWpalJiawJOGW3x
rOJm9we3a2w0MfeY0m5UxUALrrRjzzidESkjBeIRmZerH8fBrbIaGO2+aUTEb9+vXrTHbEyU
skQtnCIbGVV4W+jcnkN/LNLhJFpNRdm3ewL6qfpF334vGxTeV5n69dd7BNr6Bfjw2W1JOYPt
KgN8WOj1l9M57uwnO9IvHlr71Ypa51zgw1KPUkQ2gVLvDT4s9SQVsL5yYbec3N5b+5WRAFGe
ufJ3jkEMM+6GGmZusvbTyTjGGpv86tDLmmuuHRd6Wzr0ZqYva2wiNqSXlkU7a4PrrH1HuUhu
66w/37Q/nrEJ0ValUNhRd39A8MntjtrkLJ1jlY69BmWIfQ1UAYN3d6VzTPyb1+i4ass5NxFS
KQx6hfPi7M+31PtSaz/1zzfYnzfAh4t5vl1t4Ds4wMeLeaDFeSDPqrtXSyU6snyBD6s7f6kU
NJcc4OOFvELgN32AP7uQNzIgyuN8juaLbqSWFdwfZUshb3aCtsQmanLczLd0Fv9G5wY/v5C3
xMY/XBFo4b8/i3+jpn68JdDidp7k55v2xzM2Yc/XtGs2o+bvG3xYu4NOngT9rdIxISlVuvjP
Eu3SPVHKW6ITpTwyl91S/Q8Hs+Tiom999+/ru68x9ctJM2zr9wYfLuVZYgL/hgN8umkrNbCI
f2EPF/I0WUOjii/wWanHJfUKNjcO8HGp1zo4lTbAO9ryJsZ+ZSRBlGfu/K1Zka5RZmngeKpf
tKUtbxLFtsbmFcXGLl2J1AwcKdkVxWb3ZmtrbCI2uLrosixF0PHzPbHBc6k3ciAesQmp53uy
YpmalgZGqGw7tb0ft12m01skfEeDgLgYR6XeDtvFaSlviY6rtgjYLU5Fe4eHMP6epbxPMfZj
9Jxkiy3DtuGQ89Z+WkHPsgE+K0Az+QYHjG4Y4ONnyaro0MAFPvuUraZwQ4Xt/QJ89B5W171i
YD10gA8/ZWopM9i9+hO9o944sfcrI6iiPAkPkOR/Zggoy1UZHArzi3bItsp3bH4sstGIXZQw
4ZYWLYRghW7Ls+m3kbMfi2x6mBX6R7b1RhU0kep7LORmji9lpFQ8IvOy9ytW/ZvSI+nlpOML
86TauMgm4u6IqZBTAg1x46Idz6b/8kV7yEb82WTN+kq9y6BJhCym1fzuCvQfZO+XU/cvDCgF
3uCzgq+Gtxh4rvzGHq43amqGJsZd4LPPuGXf9qL5Uxf4rNyL6V4GQ3cH+LTc6wlesS7wjorj
xN6vjLiK8iyugtlvoeZq0dSFVrV2/KqmXs5rbFz5N3IuUql0QU3p044GaG63wSgfi2z8renW
JI4SSziCg2pvR/7dXO2NsIpHbF7+flVbbC5U4UmETzdzXmWjolr8AZWo1KFNGbolF4XutOvH
Iptwce255AgGxntu+9LP5lvs/Q72fr2CVq4DfFbllZy4o+2DF/i4zmNGE1Yv8NGnHI59vmiA
li8X+Og9NH+1UNvaC3v4GbPFMRnq63Ohd+g8ulNGvvqOXIjyLLMjxgBzby1rbYR94v2iHZkd
9bbt7scim5KoVKtWspXeQEO8mCbfofPqfVrrGpuemvomSyOBVtAhEb9oQ0vk1N6vjGCIR2xe
9n65aw7D65hIOun4ImUi9BbptFZq0XA/ZmVQHNGWnoypvd8anXDqizplL61yVVS3ftv7bZN6
X2XvZx2sVwzw4bpexUMdBviwGugxRwN7/PUdTd4PLf60g20NA3xW73GITExNXdjTeq8lzugh
7kBv0XsTg78RDVGexXaIf+CNI/mJKuhns8ngb3qIu8RGQ72Kf5TEFB6B0T3qderwt8Sm+09P
VJv428O9Y5+UuGiH3ps5/I1siEdsQrlRzZRr8adTwS3xCYe/RTq+Oyqdu0tJdW2FDo20HXSm
Dn9LdMLOmV/zL67K0XeNF0ecv/XeFzv8dYWHgt/gsxqPIxwdjWa7wIfP9TQZOsY3wEef8su1
D1zOL+zROyjimwcBW/UG+OjfsPTIOwUnbgZ4R6PebDB4xEKUZ1b9XapxqVECa4R+2/cMBufJ
wrvEJvuNrpwj9K1VATuO/KINu6z5YPASm8iMI4rm/ZLbg8HgHU4pQpMugREK8YhNzH1kF0NE
OdQ9+KrtmhaZabxFOlYpuxbOvfruCPQ9jqu20JnsJ5bohF2fUKEsQmagK8+3x99f2+Ovok5f
A3z4ALcmEjQo8AIflno9lYomd13gw1KvJMugk+MAHxZ7rtHB1uAX9GwbIeVUGpgeN8A7hN7E
4a+OSIj6zKY/HP5yWAYraUVbp7Y4/FW9X33X2OTkCqUUFpOIAEPHgvMOoTdz+Ftjo4lya9qr
hQQXbPH1i/bM0d5vKeoIhHjE5uXw1+JknZoVxoXeDt1K9f7wdpWOxSi9+earWFMwBzCu+mSh
t0YnzFyEa42TW+lgQ+i3A8xf1OHPvyiYOhngw8U8TU3AMYIBPl7MkwweKQ/wWYVnlmoT1Ofv
DT5fziM0sOMCHy/nFbDeeGG3aLx7Q446IiHqw7iOrETVhVEr4ARWXLOlP+9+FnKNTJTlcg+T
Mu241fvn1/LW2GjiomxVOpHLVjRfjrf05+l9f14diRCP2ITzi2rlVyhEZYadX/YMYkx2E4t0
rBi3yllL5dJROp9ey1ujE2qt5Z5bLt0UjRT9ruVtkXhfZvIHFiku7PFKniqq8y7w4bYtivoI
WMm7wIcreS7QO+hFPMBndV7uKaNhRwN8uJonydCK8gBvkBN6a0vrC/DIhKjPfPpbq3Eq2Atb
Bq3KNpn8absfuV1jkxM3ruSLVW+dQcvCuOizq3lLbDSRa3BfglnMtzJwNW/HyO3M5K+ORIhH
bF4mf9wiBlBiVBVTE5uObUXup35W6VjM+5iwuUBCvd0P+Dmv0XHVJjF3X6yXMN1Gpd4Sm99d
6uXPMPkDm+EOt8Ghw+I7zqI2yOIvMx5EbV4G+KwszpQauD5c2MOimF2jwT40b/DRZ9zFNVoB
J9AG+KzkZEoFHJq6sIcL3MVSJjS2faB3lD/L/XxyHUEa9Um4QU1sWmuYg0g37HcV12wgU+R+
XGWNTBzvmoviVqv6lhi1odmxK+Wu9yMEa2x6nAlzjmNuJmHsbeubQt9uVdfPF+2PZ2w49W7G
pZC/a2gj9R6Bf+8T/WOZjFD1F0191xJDHqiE3DGrkm9NvD8W2YQXlTkdKb4gZXAruepF9bsL
4n+W5yDqRjPAZ7WeShzOoSknb/BhtVeTCnrUfYEPqz1frdHJzQE+fJDcUjPwrHKAzz5laezL
KmraMNAbRMXrCPduGR5pGvVJwkFJvamwkEiNJQx0cNnhocQlT9bhJTbi+7uWC0vtrWdQvvpF
O867+60W/1hk4692mA6qRKJdBkvubQsbF3yT8+6RpfGIDYe3nUSPpj8iI7h5dsOblpnvCtQ/
ltnkWl1JZs5MhVE2eUug9K1f58ciG1/MnUimzj33nGHjwW/Ft0nxnTceLGCh+8IeFno5ofMW
L+hhkSepoHGAA3z0+TLlmozRuL2BPnoXjUoqhn1pLuzhpxyGm2jL5U/0DpF3GwDnS+9Iq6hP
QgRqqi6Ss/o/RYwwSn7RlpPuSZzdGhtNpZfapfTufzpc1asbSkcu8ibFliU2TCl38i8s+dpb
0BpyXLSjEtYmI1Ijr+IZnRQ2kxL1bdOXARGki3YUkOdNjUtswoTGZZHlVriUDH4M4qotD+fe
dHD14UQ4trUe3oMFDILkRTbfMu83Mh2sbNi7O8CHexs1KYF/wwE+rAZ6sgp2ugzwYc0nnAhc
2wf47DGulNQKaDs0wIefctYE+1D8RO84yNXJBOkIrahPogRqcq2XqRR1wfdqN4Q0n25Q2fOT
3CU2EsWjVsOIimIlBgt7W8qUr/aSu3V4iY3vqKWLSLHmjGCj6R0TUznftgP+fNP+eMYmJJ8L
JP+xRi4zbHuyo6/KyUx2F0tsKLbCMW3vq2DpFWNDi8bM/63oOlF8i8/G4ni9S5ZXvN+3zfQx
xfcFtoMtg10hA3xW5bF/kMGy2YU93MalCT13vLBnn3AuyVcN8ID+Ah+9g0KSWgdbCAb4cCth
SzWD7UYDvKOmJ5NGvRFWUZ8ECLwyH0tTKaLdwJajvMl00Car7iIb6l3jKNpFXgHfoLwlYo3t
NnrjY5GNpmzS2PWQ9NIVzTrecjjIE9PBOqIqHrGh1GsM9vqmu5MxaHcSV+2gcxvd/GOZTm01
Wy3MOTfQxIm2FMMn+Xcfi2w4STei3lx4W4UFnn6X9DYIvK/yHMxoNsIAn9V5YlEWAb/hF/iw
0gv/EbD8/caefcZCiTJY5Rjgw0rPN4mgK9mFPdxE6MtpQUNYLvBn67wRUlGfBAf4Rs2KKrew
yc1gfdcv2sGm2mTxXWRDbNIz1XDJreiU8o7w2fmU8hKbqEpKjI02LmqgzouLdlS+aHJ0OyIq
HrFxxVa6dOXIoO4KWrJu0nlZJ1PKi3SqCZM6pYgGzrCF4paj6FmfwBIdDls0a62HJC5gPf/v
OqX8t/ccbGio/QAfruSVmAsA16ILfLyWpwIqqAE+XM0TX9nBE+UBPl/NQw9DB/hwNa8nKmDN
e4A/W+WNmIr6LHSjixr7ShUTQWBPW1y047RWJ3a/i2yYpClbztYF9dU8UM1bYuObg1ZdthYp
rXOBq3k7CkZTlTdCKh6xCZUXESIqOUvLcExc3+GiyHXicLlIpzZxReS/yZhUg0Xrjm9pJqFf
vWsP6UQ5j01blPIMbIjixbTIb5H3e7gOciew0nOBz2o9pWRgXuGFPdyzFTtQNA74hT2s83pS
dBRjgM8+4W6pEqrmL/DZal6TZAQmnAzwBi2ht91F/7PbSKmwZ5kbTf1nnKO01lzxodW8Lae2
eu85uMYmRjpZqfk/2W856Py5pf7lOu9+7V1jExuYsP1WqjWGodHh4c+u5tnIqHjExr906t+6
aDPkJi/76nM6T/iXr9pjOjWqrNxYmJqBXTB+1RZ7abvfU6zR4Rj6aRofAukKC721PcXvLvTk
MzwH0R6fHV/WbfMh5939pKENZRf4cKGxR3IQeJR8gY/Lz4y2cA/w0accJi7ZQHk3wGfLeFUj
BBss413gw09Zw9sfNO79id7waeEyEQYjRcOeJBv4A3ZJUCXsiNlAF4C6J/at3DpX/Fhkoyms
e80VqIiigyFR7t/AZjYMvMYm5norS4tWLieDzu+nHeHnU48/GyEaj+iEX59kaZSb/xstImwy
+btttfuxyIb9VcthFp+1toIewO6wzsh6uz34WCQjriXN96K1kVVDOxfku21wl9L7Gou/eOyg
Pd0AnxV8UeJkMEZsgA9LgZK0wSknb/BZwafhrYr6w17gs4IvpmcETQS+wIefMluK0hbq2/1G
7zhbnmTJ2sjSsCf5BjVRaaU1i3R68MX1a3b4FZZ8PyiyRkb9PlcrXGPmlNBckB0RcNzypOK4
RKZHZprVLF3C/gWTFH1PZNpU7Y0cjUds4kMSSo+bxAsHV4P3DFbcW0muspGas4TZXm2M2kCl
Heb9LvfuoxPX2PhSTkVb9tetUwXD+fyipb73b733Wxj8GXisPMCHj5XDWhhs1xjg0zWfhPaT
XNijz5h9a51iMA91fHmjj95DKy1VBWuPA3z2KVe1RB0s7F3gHTJvYvJnIx7CniV3uC6qteRs
bBkcv6pbGqH8vtx376+x0dRJC4uF/QqBPnJx0Q6hN0lUWGPD5G92Y2pKjBuHx5nnDm00Mfmz
ERDxjE6ExBC5QGJhBTvVt5n8TUrIS2wotZpLFqFeGzFIJ67acrT8y3ft8cNpliuT6z3xPQVs
8rf0cL6l3m9k8sfg8ceFPVzYC2N60MN+gA/rvXDwhY/43uDTiq8lQy10fqLPlvYs/qPoWe4F
Pqz4RBIVtII70DvOcicmfzYSIuyJb39NGtkQRSSO1ypYUE1lh0oqdFcO+7HIRlNW7bEQl0hk
RucstqS1zY5yl8jEqWzktbTsy3ADV2FarLg8UXwjIOIZmxTDPMVfsuLaAjRNOWDrvMaGwp6V
yHftYkUymHrjV+2gkydj6KsPJzJVSmlF2Bjdyy42FX8rvi82+avwuMgFPtyxF8slONY6wGfX
/9fENLhWDvDZp5xraqh5yQAfvYeSSzimoLHeb/DhI+Yw2UVHgy/wjrreZDTYRkCEPTHtD88+
M1XqEd7BaBPVjj5+X+gnS+8im6zVlbBari2DNhZ+0Z4D3Mmx2hIbTerrrss8omhCxNj4RTuO
PGdGfzbiIR6xieE4zf58XE24QAI/kZsMYKhOSsiLdCxm6k19D2dNcJW3JT+P7yadPxbpcFL/
OToTZiJc5el3XW+Dyvsqp78IsoSd/gJ8+BDXV3bwE/6CHhZ6ca4NSoABPvuEhVNHJ28H+LDQ
e00ygDrvhT0s8ySheesX9rNF3kiEsCc+/WHYZ1X9s86+3WDU/7jtSGgrPCnkLbJh10UsufUc
Phao/8sOkTfzf1ljo0nIxZZ1l6zSQR85XeyVfyLyRiLEIzYvB4R4MMKiKoQlMG4SebO4jlU6
FrsU/12XSrXBdLbkdczsnNfouF5zzer/ZNZc0DCCxXGmb5H3xS5/Bp4LXNjDhTxNmdAD2wt8
vJAnaNzQG3u4jKe+QIPbzgE+XsbjDvqqDPDxMl6voHvOAH+2whuZEPY0r0O6b9275t4U9cTb
k9cxO0FbZJNLGK6FLjIFh4hPlPGW2GgqJGLacwsdgZ487zhGnzu/jEiIR2zCw6Xklo0z10hk
O+rjLPcOf6t0zNWdmPXSSQnscTpRxluiE2U8jmBG9neug2EqcdG3wvv3Fd5XWfwJgR1RA3y4
jGeJ0R/WAB/uzaPUBPySDfDxUp6icv6NPSv1XKF3NDf1jT0s9FoiAlNq39jPlnkjEsIexnVE
HcK6aRzWYuWIvKWXnF+pAHdr7yIbao2pU2dtcB2PdlQlp3W8JTJhyRyztmZEmUF/v011vKnK
G3kQj9iEypMeQ9AccyXlqL8f3U7I/FimU191SVXmLgZu613lfa5XzMcinSjJ5dqouQCvqFvh
37WO9yn+fvBI9pZcp23DIecd/ipaRh7gs9ozUxLUt2uAjx8jV9SdboCPPuUw7Wuoj+MAn1V3
TVOpYL/gAB/eYWhNFa13/0Rv+LRMHf5GYIU9CRGoKfvfzX8nFCkCmAStWzzkuPKdavuxSMbf
BYuOQbZaTTO4w0o7+hC45clUyBIb9g+YlOxKvWspqL2QX7ThTZtbvoy4ikd0XgZ/4vsxK/6A
QNG2yeDvvjT3Y5FNVNmkcddamxiaD7pYmnvi8LfEJtz6LE7F1QrqVxYNMn9HBfqPcviTBnpf
D/BZwVclMaHpwBf4tBRIrYIuiQN8VvDFZA+4eFzYs3LPeoqqBDgE/AYffsbSce/zn+gtcu++
5NhGbkV7kiVQU5QZ4mheLBew5Fj3VOlmhs5rbNRvdGHnUomlGmr8shaB9d+MX+7rQGtseupK
nKVUV+OopOhbTv2ncq+N1IpHbF5WoZlcekW/HajFtzn83fs5r7JRUZdGuWfO2K9mtUL350Py
21mXj0UuknLhVpxPxEeBB2Wy2I/xrfZ+B38/Q8NjB/iszCs5+XcClHkX+LjMYzDd9sIefcYv
xz5Bz6l+oo/eQ/NXS9BgtgE++5RrLalldNx7oHecLU8c/tpIh2jPkjsifUBz7tIy2g1RtxyR
8Ssj4G75XWJTEhXNLiBFW+0gm7hoA5te7g+X19gwpUa+ma5GjQ1s73xdtEMbTfxe2oiHeEYn
sYmYNRfjvns86vciZaL0ltj4bW7Fem+9OakGynDaMl41dfhbfTiti9ZCYS1EuMPf3zI87h/l
8BcNErDFX4APl/ZK6g08lx/gw5qv+88Arey9sKc1n/9HGdyMXuCzio+j7x1crQf4tOLLqXfw
Hl7gHYW9ibtfG/EQ7VlwRyEhI9PSmzasFLbJ3W92kLvGRlPEZomRdpdIaF1vzb7iz3LvNvn4
Y5GMKzcl0ghTiLg2sIs/LvpsuTfiIZ7RCbnHxvldQTps6Hw/nLTGJlS1P5bSq/YiDWx/8qu2
eC/O5N7iw2lWsyn5vzuh5uFprVzxLfe+2N4PTWq9sGcFHksMY6EzwW/w4WY9jdkPtFnvDT77
jLMlApuyLuzROygiYamAHSC8sWfPlgsn6WBi+gDvKOdNRkXaCIVoT4z6Y7jXv+xFetHwPT5p
7FcmzVOrbISUa9YmNVQEyGbHdMV0IniNTXj0WeXSokmPC/hz3TMRPPN8aSMS4hGbl7GfdjZy
PeSLBmZhs2ki+HX35q/aYzpW/CVzMWQh7Qmls+NLOp0IXqMTHn1MTsSlcOcKTwR/G/tt0Hdf
ZexXCfX3vcCHT29rIkWnMi7wYaHX47bgQxk7fLAfzQPnlOGp7wt8XOg1dDRtgM9LvZJB85cL
/NlSb4RBtCcO/WHv1ylrjlnailpm7rH3qzqpryyyycKmufXw5UBbef2iHVLP7kN419iovzbS
SSjn2ioYpxgXfbbUG1kQj9i87P18O5GtxjMCk163eThPTm4X6YS7UOFcuXNj3MN5SwMl3ynX
j0U6rtpKZM28dF5Hh838om+p929LvdP2fiURHGJ0gQ8X8zQ11OxqgI8X80TBUs8AHy7mRUMS
6Aj7xh7WeJwKuEBf2OMKrwoo4wf4sxXeSIJoT1M6tPpmjXo2NGtgl73f7Zjqj2U2uRuTVslE
qCY6UcxbYqOpsApV9T9b0e6KuGhHM9vE+KWNHIhHbF72fixNXOB1FrA2eULhLdIxLdR77lRe
svW3KeYt0YlxYN8ZURcXq0qfO0P8rfB+B3s/Tp3RSLYLfLyYpxUs9Azw4bY8/zwRaA8ywIfL
ea49GuoZdoHPSr3ckyp6cHuBD4u9qHKCZe8B/myxNxIh2sO0jkq1qmVfgdFEiE0mfzox+Vtl
w03Yly0pWQlsMI6LdnTm1Uk5b4lN+Lz7iyOukHwBRptp0o4v3lzsjTyIR2zeXs5SpISoKPXo
ye1rsGv+qj2mY7n1bq72soQP8lkv50k5b4mO6zaVzJKtlGLgLycu+juKvfyXd/l71GQOtpdv
+EZukMZf5T2oaLb2AJ8Vxjl6fkHZOcCHhXE0WYMFvAE++pSzlggeBJXxT/RZ4ck9xcAcJjwv
8NnnLKa+LPz5Qf9/AAAA///sfU2OJTmO9IlGEEVSEi+Qi4hTDPBtvxlg7r8Y8j13b2AKrjRX
KpRZXdENNHphXhV8cpdM/DG7W+gTvYIc3855OGU5zTT6I4ODkBIk9oOR1Qz0DqRF+oNa7r3s
5sKRRJECbc2aOm9B+SQtSYXqIBU6FY2lbKStVqeVnUBFb1uiFeS7++AednppPIomfMVNcnN+
DDvi6pIXrWQd5NyngiG/g9TStfmnw2jh3h9aQY3ZBkMrU9FEaSNLtxIi+ArKbMzWQ/50avyP
kh8UBSu2J3gv5xP24x1lKy/sZsYXg9uofsQB3sz4OOw30DHvE72Z8dUkGbx7nOCtf6FFjhic
Gz2wK5KHPJhRPk01+iOjA03qJM+ol9YqYwkdf6iu4Ec6MBubC4fDpS+Ha3G1ToIdwrymjN/q
ID81FY0mqzmzOt0T3yuwSrEusvrNd9z1etV+PI2GxDyYHP64Cioa6xJX6ZLbYBx+KhoKV2kj
Cas+p+Qw3VsyQN7utoHP6Wistu5LEzPxDbxX+EPfMyyL6N5+/UElcD7kBG/meSUJbEx6gDcz
PY5+O1SM5g3ey/TUzLdPUE38Qm/9FVtxAgKqBB/YzZk9bakz2NZ0oVdwvdtUmB/Ap3lFf+SP
UJMV1uzvYXFagZZA/KEVXK8PTuCpcCQ1v51obaa1VNBALR5akdmjQWZvKpqeusR0UW7klxmw
2yceWsL17nj49ar9eBZNedW9o9mhWMmor8iaqvdtu8jHZDA59RLj5EFcOWdQmiqeWhFOGUhd
ToVDSf1SL61ZUSJUrMwf+uZ6i7je75If1AL2OZ7gzX2OL+8AlK28wZspnyW4hnSCN1O+Rqmg
zP5C703u1R7WRmBy7wDvXWcnR6k1cG7iQi/pdbzPutjpYGGPXBLCKSRb9Dj524ju9qvsRW7n
Yz8mwwkdd/+RelTaChu2WciaZsfW70nfXDQ1SXc23lX9/Slg9tUfWlLO5fv7hZ0mFo+icQLn
1wrRkAOvsHW2LdHcGYjUzAXzEqnxA8acT2YCB0EWjbXcC0R+TkZDiapJ3P58iTKqoDspEPnN
+X63BqGAl+E3di/LI0kZbBw+sHvP/hAVJLA6cYK3rrCVluDWnzd26y/odA2XmD7BW/9C7ezv
FUiST/ACAkFybylip22FPbMUkRzFTj8AqXfDXoq6RMbY7zcDcjcVTUlOgKWJ0yGn/OCZGw8t
IXf3NbW5aHzvKjVrt0xdKija5w8tmZW4zRpdb9qPp2uTTYidq/p/CZZAWtJ5WG71vz8mo8nJ
6ZCWRv62sYJGXPHQl7Yefk5GQ4mp9hxyQRw5SrQWPfXdfLO7P0OBUAWcfDjBe2keO/EQUMj5
BG8mepZqQ+XYD/Beokf+s3TwLzzBm6mev1oE9oue4K1/Yaj2GDzFdIBXUL2BTbCdlhX2zE3E
T91oL69aRBi7oPhDK1T79DZX9DEZjTODSsVP3l5rxqneiskjehlv3h3Ak9F00apZrHVisCfE
H1qigXLbdni9aT8er42fGVRKL85DBB2PX3EN9mh++qY9jMZZW38lV/0lbtrBYvQirnc/Uf45
HY6J+XdTnRQ7Ea+wQOS3BuGvk73dGoTipKOANY4DvDmZp4lQS5sTvD2dxwUt2R7gvSyPI1EA
cvkTvJflEePCLyd4c0Kvp6boBOEBXpLQu5/HsNO4wp6YCdQwE2jaWth4KTh9W9fYrCnd64XM
RVMStUwqtVNmQfeJJb5k1G/VTz4no/FPr5nU3KrTb/hOkfKCb6Fku2/Rs9O24unahANeqf66
mYATa2XJYHQhGqSOp6LJqWVfFafgJM5bwdx+XmKuPc7oTYUTyTnJxSir7wfg6fWd0FvC8X6X
CmEDq6IHdi/Rk5x6A2t6J3hzbx6FBjestJJXHDKPaF5J0hX7lE/wZpoXpVg0mXeA9ybz3uV2
NO39Bn91Mu80rbAnRgLVOY6EM3DnUllQmreEGKkMDt+paIIVFKlslTKhvVJrqAS123b/z+lo
TFT8HpMtR88k2se2JJk3qtuelhUPo8lOV0NlgPy3MjiZt2IUo/RBMm8qmiBspVsjY21+zURH
MZbQvHu3l8/pcKwHv6sUcj7o1E889e9I9PgrFAjB6ccVY49/a6U/VF/tBG/OM1pqDGZCT/Bm
+pkTKmF1YLeucZFeUmVQT/dCb/0Nq79aSqDd+wneu8pV/GgsoMXnAV6wschAAttOTw175HMQ
A17WGvdu8mAsZIUBDqkN+rmmwgk9RZFsvUSmjNFZ4BXSS2S3nhqfs4vjJzyXXtWYKmo2/npo
SclyUE8+PTUehaOJiUrcEFSlgJ3L8dCK1BwPLjtT0VAKKW/uRs0JISgB5Q+taeu8ywJ/TkbD
vonGKJU5u3Vijb1qPOmt86cT0H+Uzh+DfaIHdi/f01cPCjrF+gZv5nuapBOq8/cG72Z8FKZm
MON7o/cyPrFU0B7ME7x7nSWB8qcHdgGlKHZvRGGnrYY9sjoIWbhi1UqWzGD3IK3RkiMtg+nM
qXAkUdNuvSuLga4ai6aA+4juza1NTjlnKf719dxAz/HXQ0sa7gZXi9NV41E4moowZbWquTI4
ihgPLaF7g4zjVDTkh1+MOpl24g4awsZDC6KRUffgVDScSswi+W6fOws4ox0PfdO9NXRvs85f
j+5X7As8sJvLyjWRgafRCd58/ktqMM17YfeyvCoxzgmO4x3grb9gq/I63jCJvwO8d41bK6mC
RPkEL8nq3bUN+dF72kPYIw+ClvzgdR7K1H2fB19bf2hBqoWq3MmjfEyGI8nYr001Iso1ozRv
iZqzjdoH5xaHQi5fW9insRGoGDzrLfuXrN6gU/V0iHgUDvuHKlaaqcXMC9g2soa0jjT+5qLJ
qdemTh+1laoM2ndEn9MKDn67EXxOhlNSJl+a2vyKVA2t+vhD3zxvEc/7XRp/RmCZ9ARvTuz1
1FXBRvADvJnwWbIC/oYneDflK0kbmh090XsTe70l2L/jjd1M+XLoCqKWnyd6SWpv0Mh/ukTY
I+3+KOUK5WJsVkAd5NdDK1J7eZBwmQpHUnFKwaxhSIJKlckSYwV6pRLvDuK5xYlLdaHcuRRl
lJHHQ0tI30/ftR/PwinJ2atGPE5gW0M7PVc0kjjpG4wnTUWTU2tSyelezdU5HyoDs0JQa2ji
MRcO+VlUfYMJSu7/dLQyPdc18E36frPIn0lFG+Hf4M0de37VA68dL+je4z9mAxg1gT7AW1fY
uKVawMLjCd76G3J5KZJgv+EJ3ktCW0/VQDWOE7yARQyngk9zCHsi2R8DvmxO8uI6X0C5skVT
wXV07E5FU1LRIA+5FBYFe47ioRUMb1RSm4pGnKvV3HOkKrl1jBLJIim50WXiNId4uDYUUnK5
ioeEztOtkWAs+ZZ9f0xG41SN/Xux7I+JLxBGv/2pJbXogXPHXDiU1K8RhVVLyVpRFee5nt1v
gvdn6PzVDGZ6TvDmCq4mBt/EA7uZ6Vmq6FjwG7uZ51liA01PTvBmnpf9VwF79E7wXp4X8zRg
Z86BXcHy9LZHj3I+7CBe/+8Jzyut19qUKUdOAuR5K9R2/OW/ralNx+PEQIpTrkLZIwL9LeKh
FX167S4z+TkdjyQOUR5tmYspOJjhD33xaPAVz4/H6+MMMkvW7j+XgrnWRaLOdGsw/DEdT47+
m+rXYSd8CvcexlMrAqJb/+fpgCiJ81b/fsQXyAgeNvkW+/t1xrdf7K8RmKw4wZtTepL8TQRz
ei/s9qRe6WCvwwn+Jnv/h+y1VBuYWD7BmyvLOXEHyd4b+7UpPd/R6SITz7w7lLK02p00SwGL
T3Vy9O4vvXp3iaOP6XiKk9ds2nslP3zhnqOyIkn5KkXenr1z8cQWGxZgpbdg4zv9hUeJvSue
H4/Xh6hwNFOKdAEbcsuS3tBIWf30fXsazyu5F+554dLWK9hF/vXJvemAKEbyjatQzH6jLh7f
2b0VXO93if51tCfkBG/O7rWUO6oNeoA3t+tFDy5YhTzBe0mfaAIVQ97QvYSPLKGJpgO7l+6J
n0AGizi9wV+e3SsXoXjm4FFqdLWVLq+DC83urSBIcmtv9jEdT3CDzsRUosSGev0ssmuz0fk7
F4/fCLVKdoYU5nOozGRacQ3/SXavXHzioY9HyHrU1s35JKy+vSS7x32UTZ6LJ2T8Gks3YSLO
4KD0ouzevZDM53RAISXjgRRjf+PgiaA0V+L70xnfl6j/Eer8sKSEsmx6ZL/+n39TuP5fgPfy
0JITK9i+cYL315kVlJ0/wVtXuUjX1GFLvhO9ObmnSSr4Jp7gvetcraWGqn4d4AVbyyvxfssP
+OI7j0wGaqphyJO19UZov3g8tCAgldvBkemAJGnPpWvv3KmDHrXx0IrGwnorzTa/QJRYpIWn
a1ZFM0Lx0AoGd68DeAX042FAIernl4VmTahJ3aoESDRKec/FE8PZ0qX4KpWQckcJ3JIbg476
G+bi4Wgj97tI9/3ABOOj/sx3BnIV7/ttYoAZnMk9wXvpX+WXJSU48PoGb05DSvJLNqoT9wbv
pn+WFJ1xu9Cb6Z+fXR075g7sZvKnPVFHpzhP9Ar6x3fNUnEYy8UunpgPOJPLzf/JmnPRil6U
46EV9G/YbTgXkCS2rs3868+VwaS2JFkyOayjfOTkAr1MzUoOGWhRtIl5ldnFvS7gFdCPhwFp
KjXnbNR6vHPYZ6SLEqy33Xkf0/GEqrPVot0sxnlh+reCnpfb9fmcjoeTZpb4NqWZgqpn8dA3
/1vD/zarA7ZIQxkoF3OA9xI/jWZw0JLsBG8nfrmDf+EJ3kv8qv8uHfVOOcBbf8PWi+/xYE/f
Cd67yt2PVS5gYvJCr6jb8qguqBeveORg0JIf784p2LlfA80y4qEVhdvaRm3/cwGpc9LaqhV6
5f6wVdIlogNkddT1P7lAlJr4xSGUPFoFPSPjoRVzJi/JnZ+8cT8eBuQ3clJ/00w1BjRgrcAV
rZSstw4g0/Hk1LuVrsy55C6gTIM/tWRwZth6OBdQSWF12MMlsAuaC5p1Cfxmfn+QXmBlsBP4
BG/O/GkyA6nBCd5MAM03A7A088bupn/+qxCsFnig9xJA6qkWsM30BO9d5VZr6gROSF7oLy/8
1otfPPI0iBouVcpmWRk8jlcVfivdHV8f0wFJEnNaEQo5YUqNzuXKisq81Vsdt/kFIj+Pc8vM
ftXJoGPa66Elhd8RAawXv3gSUEnB/Uj8eh4GKpvFom8FjKbjyWEtrkTOmbg1BnOz8dQKAngv
Fz0dEPkCleZc2ZyoC2o5mOZ6W74J4G/VDozbGOr2e4D3kj7i1BgdNH5hN/f6hSAgSJtP8NY1
jtnhVsDEwQne+hv6zTkR2pN+gvcWo63HoQX2Ih7gBXxiPGrcLj7xxA6gJuldtHZh9n8+Onmy
hB9VGRXe5uKJqWHToho5v6aoDPGSJm8bFt7m4vEtosTdWkopTcHu0thXluT7RqPG7WITz9aH
CpXcijn7MnAfWqYiOMr3zcUTQ8PqaxODW40UF4pewcclj/J9cwFR0uZUvFKjYopaH012yn7T
vT9ESRBXjH6DN9d6X9k7sNT7wm5mfdERBzatnOC9rM/JejQig7PGb/Bm1iepNbDj4ARvbkFs
zpXADfEEr2B9w3njfrGKJ34ANXGutbTcVBi98dUl3fZUb+P5mI7HCRy3bpaDK1VYrW7FOz7S
jZ6OR2KL8PUJCT4mcHpAUl2SFBuyvn6RimfrQzmUSzJZUSqorjctiWfI+ubiCdZXycyZbC/h
AbST9Y0FZuYCeulHs0rOFCNSqJrgt8LMAta3X03QCLynnODNSb649KLWvwd4e5qP4aGuA7yZ
8GU/rcH63QneS/iKJWpgf8wJ3pzms9QYFPs4wV+e5rOLUDyzCfFj1y9ulnOTBhO+RYqCozTf
XDyvNF+32jnkWAhsYViT5mu3Aiaf0/H4JiaVJTrGlAws6/pDa9r6RoTPLj7x1CyExTKr+eqA
8SxSFCQaDRDNxROKgtablFgep0lYV88WRcG5gCLNVzwm4kqVGOwj8Ie+Cd+vE77fIykYnZxg
wv0Eb07zhS8VOo5wgDd39EV7Lzg+eII3876aegO58wnenOiLZA3YiX+CNyf6KBUDZ9xO8Fcn
+uiypaCntiFapcVjXQs4QL2GJ9UyOIcn4/HXIYcXb21kXMGiRTy0IJ5ebi2Ap+ORFKLLHD4b
ogI2i8kSg+axsCBdrhQP18fZpPqFsolIh21dlggLDkzipuMJ3ifGFjxWazbshYunlrQnDvpH
JwNyCpdfWuxZpRi4QDR5EfzdvG8fq/uf//yv//ff//8/aEVb6oOjCmNzm6uhID1a0RG1gI3/
DlnF8DdNGZ1rvdB72XiuySoqrHiAt5fdG5onPsFb17kwpdpA/ZQTvPU31Oz/0gIOqZ/gvfeF
1uLlB+8LB3gFG6e7VvpgR5dvCD20cZDG3GvR5oQCPnxX2BtLG8h8T8bDidVJitNXFjFQyp6X
mN7Ra7LulhzNxVOc53Rn47Vm6hn2QVnCxstt1vJf79uPh/HkVEqtzS8XncKBBwvIn1rCXmnQ
5zEdkFhuVpv1cFAB25XzknZlX6BB3n86II7htBYNvpkJnhbi7zzsKub3O5KxTulaUkZFoU/0
9jJ8gc26DvDmdKwk6eCd/ARvJoA99YaWJw/wXgJIYXwDtoOc4K1/oZMLP2FRp/MD/OUE8PIR
oWe2DvrqGzOL8V0wxbyMAA7K8JPxhOKrX/v8H+2HVwHVL3lNH6nVwazrZDwlpt+tW3tlx+A+
xRXT76Xcppf/9b79eBhPULkiLedu2o0EC2gRAaT+8xfueUBivgGFyU/LHS0A5Ekhwr/U4Qe6
2tMBsdM/yr30kNpvqC81f49XLyKAewu05N956oxu/Sd6M/PrKUb0QOb3Bm9mfppIQJ+0E7yX
+UlNflUFJbVf2L2879WdAF5ATvBm3hcyLGCO/ASv4Em39iNxDl92HfTMDUL99O1SClUqeHv9
iilrlVFZdC4eJ9mafV8qfgzHHC8qB7yCx9qt7uXndDxO4XwLqy0mk3NWtF1xCe/jPEr8XW4d
j+LJrzYJEupZOqPuA3lJn0Sh237Sj18ISDSLv23UYioZ5bGypD/2VvXo8xfiYV/33n2ZemPU
iy6e+qZ9i2jfb8n7RZFPFZ0cOdF72V+RhHuCHuDNHQaUSgOT/yd4L/tzytk6aEN6gjfzP0ul
gK2sJ3gv/2NOguZOT/CKvN9tG1mcx5dfBz2zg9Cu5h+KVSGCNdTW8L/bNr+P6Xj8x65Nagl9
u2IFW6NYoRWF35Gs9mQ8TuV6a5qJuDUDx+b8oSV+yHmUZ77sOh7FE0wuVM+zlF6zgbJB/tQS
P2QdXThmAxKV/FoiJ7Ri6PzNCgJINnIUnw4oFBUbkfonJA3MFOTJ3olvAvgbZRV9608hFIAd
tQd4c69fTlRBAZsTvLnXr/hpCJLSE7yX2tcWexTI7A/w3lXW8EsFi3QneO9fyCX5loiWy9/g
JaXe0eTN5dRBj5w6ku/rzE2tVa5g61U8tCCeetup9PEL8TTL6me75Z4b3LvYlghp3yqdf/5C
PJVj0rpKV7/FopR8ztH2L5RvNHlz+XQ8isfJW8hnh5VK0bBUQSnfktGbMir1zgYk0VoaquBa
ixM/lPKtGLkmG10yZgNif99I/IJRW7irowF9m+gtoHy/I92nlpN18Dw7wZuZX01gA90bupn1
tcQCT3i8wXtZX+MUzeLYX3iA965w5cQNNnl5g/f+haJ+dqG3jwO8JNF3t8fHKXzZc9AzswRq
vVAp2ropSipWvBJO+u7ySB+/EE7rzQlSjL4KgcL7q0hfHWVdZuOpMQxvpXehlzAgRvpW2Awz
jfoKLm+OR/EEffMrBnXf/Jp/FShHWkP69C6gj18ISESran+1LBLYKbGq0KujQu90QKTZVyfG
0zuBDTf+1NQe/E36fqOyovaefOvHzrETvJntUSpwafcAb8/zUQP93k7w9jyf367R4vMbvD3P
FxNlcJ4vwNvzfJZBZcUT/OWM7zLooGd+Cc74qvSQhVMFm2YXUT7po06r2XiaxZRyKz07R0Ip
bF+hsGMjobvpeOLc5cxatBOq3ZVWZL5LufWX+9f79uNhPJHnk95rya1FvyKaRVohLOAM6ecv
3POAhNla1Za5diKY8i0ZUpafv3HPA2JTE20aFtAKN19+5/lWUL7flefT0kDmd4D3nrjkbyVq
r36CNzO/nkIUA2R+b/DmXJ8mWPT7jd2c6fN/Z8W2zwO7Oc/XX9wCzPO9wUuqu6OGvsugg575
JZAzPsutZv8f0ApwS6JvNp7Wm9/2cuesCsobL0r0tduBm89fiKe2GHytze+Hzv9Q1reg+u6s
b9TQd/lzPIonUnathUJky6V3uLrLXz/QMRuQOD0qHlUOYX8wFbsq0VfuAvr8lYAKsV+YsnVD
9W3/XfN8DJO+J7q8oCLvijNj2ZjJdmFBScTgpf0AbyaiLbUKUuUTvJmIWqqGGl8e4K2rXEpL
PYM3/xO89TcUq36DAFf5BG/9C1l7MvAPPLArEnZy18gW1OCyDqGHTg7+ndRqqlQFlHKkJaJ1
P9GUmYsn5GG0FYtJ3E7gjL8/tCKe1kfpoLl4SmLrmc1v1SKokGWZzAb9hYqOGg0v55BH8YSo
YBF2Vti7byxwn+ESkcRbr8WPX4hHutS3jqXfFhrMRJdYhg9HS2YDYs1K4iRUfInA1p/v0ZK/
v6YgpdzAM+1Cby78OePsaAH6AO9lfxruCmiW7wDvZX/sdKmA/PQEb2Z/lqxjB8OB3cv9qqWW
QZ36E7xgs+fRmEm5DETKQz+HYtydLJFkA5tPZo1b/6IsMxgzmYyHU2H10ziHTbCAjSC8xsl5
yP4m4wn2V5SJpWdhRQ1R5uTdnigKlss/5FE8oQ3o1xhfIWNhNJu/Q1J6OiDpVmskOf0jQge1
FklK5zxIfU8HxNEckCnMF7sQqpUz16X0Tf/+AEVBTuhY5wne3u7Fhg6eHuDNrC+mCsCq1xu7
l/O9Oh3B0u4bu/X3U7YkoIjVgd3L+FpJtYB6PCd4BeMblQLLZVJRHpqIqL2miluv4GyZP7OC
wA6lZCbDCVUY7s5gu5Efw9g3uEhKZkz45uKJ3cu3L/Z9LFxRsGzSonQf0yC9XC6Hikfx5ETW
zK8Y5oTc/4tmk5ZICWYd5JenA/JVCXZUuYT7KSwls2Su+LZ34/MXAuIsNWSkfVMwBe+1s70B
34Tvz9ES5OhtRonfgd7c8tWSoXeqE7yX+VXyDwEsmL+xe5mfxlUTzIOc4L3cTyRVUDL3wO7l
fr2mXMDG0hO8ou1wpOtWLn+K8tA/xDlY8fsRW0yxouTvyw3kJuOJafOqtVLkqAncJ/yhFdx8
TP7m4gnyx+TEohYSVOR/UbZvnF2+3CkexRM0znc8ZolJiQznkjaQv9mA5DWPq615YLmgsnuL
yN/P37jnAYUKu+8F/nmKddw/5G9p6Pxnkb/tOoI1FQLVUE7w5ua+MIgFLRtO8ObmvpD6B/0X
3ti9pL7WVHFp6zd47xorJQMHHg7s3r+v1EQNld4+wCvoXr3rKY/j97KlKM9sQ6h2X2CWRiKg
iu8qDcFbuZKPX4jHg2k19xolKoLlZJbk+ka2IdPxhKy3rw0Xbh2cuF8j6z2eLS6XK8WjeF6z
xVyaUi0FdSlYNFrMtzMZH78QjxTrOfKWPbLlWyeLb69/n78QD3ft4SHk16ZW8Cmgb7O4BWTv
t0wWd0sdVEE6sJtP2+57IHjWBnQz22upGOqyfID38r3mJBg1CjnBm/mepYbKTJzg7e0FVuGm
0jd4STvfqL3qMqIoz4xCqKq2yjEvADZXbSF8s+G0SIapk1irGZTwjYe+nPDNxqPdf6iW1emr
gtkjWrLtlVJG+eTLheJRPDFWHGMpRRrnpmCZYZF+INnPX7jnAYnkEqPsWXru+BjuivzeUExm
OiA2MT+XVFSYwX6Pb8r3t9QPbKkaWKg6wZvze2G5AAoaneDt+T0/QdHh3Td4c4ZPUwel7w7s
9vxeQ0Va3tjt+b2Cai2d4C/P710eFOWhR0itRZv5tY3+KLo3G09ruUsLcWVBy7mL8nu9j1rp
Z+NRo2KlZYriJ1xuXzO8MbAFLpcDxaN4IlXn23JWYlZfItgWeIl2II2mhWYDktK5lZgM6cYV
LueuGH8yG8hFTwfEXYz97lKd8DW8l29qhb7p3p+hHWjoSOwJ3pxfkVRBXYkDu5nz9UiL4cqB
dYky30OXkAxXdQ/w3jWuoZOLOsEc4M1vofq2DY7AvLFfnuO7TCjKQ4+QKrk6r8isFe3fTUtG
kCuNqmyz8YTJXTb/9olRVe8tSb7ZeDQsZoWd9bVuW5N8Q5OQcllQPIon0nXhDSfcWYMq7Uzy
jZv4ZgMSKY2aaHfWl2F34693hpsOiK1zlN6ZO1VwG/53VYz+EvFAQpulV9x1/sbygS31gm7h
J3pz/udlDAmmf17YzWzUEsM+EAd46yoXzqmh1dK85Jx+KB5DCgqZnOCtf6GTtuQ0BxwmPsAr
MpA0KgBe7hjlmTuGhg6vkzerBprQb5knmQuHU0wqZCm1W82KEYN4aEU6qIzSQXPxlBScrVZu
VURBa4yyZD6mlDJqMLysMR7FEzKAHkfYfZQWDO6PEQ+cDki6VvFITDIX3N5tCbeWUYvhbEAs
lWvtuVJ4P8IJyG/xwFWU7zeJB4bfAthhfoA353+CKoFOuyd4L/NTSYxaJ7yxm3kfpY4nct/g
rb+g5mhwRH10DvBe7lclRb8UKB34Bq/gfkMpt8sjozzzyHDm50ssViNNAyvJrHB6GwpHT8bD
qWgkbP0Yzp0II7Px0BLyN8oKzcXjPE6tdBLiLmAlsEzKuP0lDfnz1+3Hw3CCxSk766uce0Zd
SBcpB3K9C+jjFwKS7rycm7SWrWXY520F95Nbdv75CwGxclfWRjl3LbBy4Df3W8T9tisH9vQS
ccWUA1/g7aVnowe15wBvJ31+TwKTywd4L+2THEO4qAbPG7yX9glFjgxsgTjAm2lfTehc+4Fd
QfqGCjKXG0V56Baifrvv2moI+aLGdRvkA+fiYT9Olfw4tNKEUGK+hsQa38ntfU7HEwSusjjv
c+6nFdaLXmFcN5YPvMwoHsUT8oE1lM9zKOLADXobBGRm4xEJYWVnfE77UGGuRbXne2fBz18I
qJjfMYqES0038CT7Vg/8+6sH5hQ9wKh64Bu9l/1pSbmDhbYTvJf91TBRQRvdD/Bm9tf8cABF
g07wZvZXnbZjB92B3cv9WktvIWdIO/oNXtJ6OKi/8eVGwQ/dQqLdgLlV8nVGBWWW2DDX28Pr
YzoeTmzKOTe/ELB0LGHBS8SWySnA/WE8GY8TOQk5t/ALafBI+5L6te/wg4ETvrwoHsUTRM4f
4TAmbILmmJfRv0G9dzog8f/U7Bc8sSagktiq+eI8SDJPB8S5Rg27VgnjHbQ59Fs/cMHAyX79
QN9ecP3AAO8lfDEyrKhc9AHe3N3n/9KKTmoe4L3E/iUKiCrKHODNtJ5Sg1n9C7u5w1SS34PB
WZgDvCLdN5ow5suNgp+ZhVBtEhml2nuDZxm+fsJ4Op4QlCmdRYswOvO1ZtbE2iDdNx2PttAQ
FKpG6Nj9KkGZkYIgX14Uj+J5KQiWmmtzBltq/XMmjKcDkmJMMXTpW3mGzXS/fsJ4OiDuXK1z
Lq2YgJmB7wnjv7OGYE9FwALgCd5c5s2pZ3CzOMGbeV9LjI4QvbF7WV/LySooy3yC965xmKdw
xSeMA7z/LawgpzjBS3jf3S4f5/BlRMHPjEKoRuthztUUFfpYNmM8yrvMxtPCJc64iOYMenYt
UpaxNmi1mo5Ha8uhIZjFP0c0nhXWOWMhQb5sKB7FE1XEXLn6U82J7O4Z45+/cM8DEv98KvsK
sX+h4JT+qkRfGaWWZwNi84M9Z86sUmHnk28hwQW8b7eQYE3WwNaEE7w50cepM9rTfIC3J/qo
gfmSN3Z7mi8+ZDjNF+DtaT6tHc/zBXhzok+d8YBDlW/sl6f5LiMKfmoU0np2juTMWUCBzi1p
vtl4WjXJ2iQ3//LhNN+XG4VMxxMGFKHuoi2jZ++WNN9lRPEonpeQYK9VKedCWmG69/VpvtmA
pHR9jfJ2U4KN7jak+WYDijRfNv+Emv8PqD32neb7OwsJ+oYODiEd2M3plVdrFFjcPcCbOV9P
TUCboBO8Oc3HqVSwNHmCN6f5OAx0QWZ/gDe/hyVZx47gA7ukm28wUcmXGwU/NQuRHk7A3V9E
0IJ5WZJvxPpm42n+ugaxIIqh5D8nyTcbT0i3EFsmEQIllxYl+YZCgnx5UTyKJ9J1TEVi5NUa
2Dq+Jcc3G4+IB9LKS4pTwBduh1nIdEBsQsr+vrFvC/9wf7jyFTqCYHloRWHo0RwCmAdasFMu
IMi/Sduwp0Jg++OF3ktNcku5gvKLJ3gzRbZUDe5/fIO3rjMrpWzgJMAbu/UX1BycF9QxOsFb
/0LuMQMOul2c4AUby0tW55ayXA4e/MRPIWYjlEMLMBsJ6mI4qWjxROBwMh5OUWPNfi/J2jqo
18VLRGGcwN7l3T5/YX1UpDdnlYWVGypwuGQgyWyUiL/8Ox7Fk19N85V6L0XFFGZgSyZ4+mjC
ajYg6RbSiVS638s6GtAagcM84sjTK9R8N2DfuPzijHo45skJ+z+dI/+TBA41dUWTeyd6c1Vc
Ih0G0r8DvJf+qTwYGj/Ae+lfy0nR6ZITvJcAEidjtDvjAG/9CyX7Catg0+AJXkGYaNQIeZl5
8BNrhfKyVqg9h+EKfLVaMyE8FDmcjMe5XKl+GDutVSdk2FvkDy2pUw4r47Pr49yctXF+SR1i
9zZ/aGr89C/0YpQjvaw8HsXjRKH66lDXnD0emC8tkW0kGwgsTQfkkVizGEcP0Sg067tCYalk
GV05plfIiuRWe1VTgdPY/55J0n+CyiFHpxNIqy70ZuYXUzcFZX5v8Gbmpyl3cPztBO9lfr2m
go5QnuC9zE9DrwRsJT/Bm5mfRL0bZX5v8IqeyD5ifpd3Bj/zzhDLTSpTowpbZ6zIW/jFZ6A2
PBkOR38sN+5F2b8vlPitKCaT1YHu3PTyRJU/q3EMJIBCKouIH7U7nvSv1+3Hw3hCEoWbSFEp
vXewA2ZWSOUvLZEj4jcbkIhJr9KcoUsH5Vn9qQW585KHV43pFSr9ZetYNfTh4czf1N3pm/j9
MUqHUlKpqCLKid7L/4oTpoyash3gzR0GTosNNYk4wFvXWYhSYZBDn+C9/K9yHHqxyv8LAAD/
/+x9S64kO7LcikSQ/ucGanDOKgRoKgnQ/gdyz4yIBl4jWR5MHlbdfomuvt0Di1vpSWbQ6B+z
BP87wHv5H0IUxJP87wAv4X8j7bnLPgPv2WcwtygqV7DKNZtZWuJtN1S6nownlK4litlmWimr
R7lG6dpkpDw3uz5iMeFjzE4uktJE8dCSzN/ovnG5Z9yKJ4hC9Otx5El7s7SS3gp/k8qjG8ds
QL7bfGE8HrWQPdxKAEfedvMrRGrQkZr5VSqZbP74m/xDtQ59cySP2gO8udevlqZJxZYTvLnX
z9+22fz4Cd66yv7a8x9n9it8YPeuMXPpmCTNJ3jvJ8RHXik7lPUELyAU+FLhIg7gyzoD71mb
EHYJZ1n/jApZTZUVxfVG9qqX7OuNeLSHk7HIY3okd1rFQysyfi8J7Pcb8Qg+8rHcW6Ws12hZ
oUXW+svK6L/226+b8QQxqNRQnVPEBSNd6l3Cj14aDn69EVA4tEBVaA0kP9W9ZB6m9dEVY3qF
ul8vfM8R+S0jWQSok90fH8L3N2gdapHkxj2wm1mflJ51DTrBm1mfFupZS5MDvJf1NSlqyYLR
E7t3jYUitZEUvjnAez8h+V/askPaB3gFS3pZF/VTmC7LDLpnaULS1T9gq9adWWRZ34q66JD1
TccTrmKMVEMYMlu1WMT6XhoOfr8Rj3BkjzQ6azRrNuov5iV13kFamS7DjFvxRKuexUS3R9Wx
JzuNZ+cH/o0k/X7D3Q+I2GmVVgPRZkknpkVpvocdxW923ERATYC7NkJ/IUCa9U1dvT+s748q
HWqBrLftCd5M+FpByJ1KB3Z7kg+ylisneHOSTwo/NIWTlDnAm9N8Uiol1/iJ3Z7k6y2bhjzA
C+gE1IGfLF2GGXTPMIMYakVT8mVO6rS1JYfVb+jebDzauzlRcQ4LlkzEtmJrHOxe0fHvN+IR
IjAhQGBoabr340k+uuwybsUT6bqQhEQVxgZ5SZUV7AhfTlx/vRFQsKLO4LvZ40neo3ck+eZX
qBs2k15rN05bTH+SfCvo3p9SOhRNdqmf4L0nbosJ+OTl/QRv5n1W/O9M9vMd4L28D6ovXNqG
7QnenOjzC0XLurQe4M2JPo2acjLdfICXJPoG0hp0WWbQPcsMshbl3Q7s7/ss8VsymDwkfrPh
aKeGVZ22ZIVcVqX5ZFDcnQ5HhCR4n8RMUJbHLknz4csk0r9226+b8UTCDrpWgOYbTvFnZUL+
K0162Q779UZAxE38X92czkqyHXZZlm9E+6bjab2imsTPM5tY/k/N8uFPaB0m82pL7m7LZkx2
qwq2Xixb7LvQm8moFpWs89oB3kxGe0nmz57QrWuMFCpySemQE7z1+6Pui4bZsd0DvPUT+olT
KDlxd2CX0NBX504Qg8vKg+4YK0CB3sAqSifGpI4jLBFBHgvKTMYT2jANmRFrF0uK/qwSlIFR
9W92faiBhMGt01FMzxWveKcA4KCrlS4jj1vxxIAIi4hpdAQ0zubr1igKymCsZDog8iMQGXy3
+T+TuhyLFAUfGhu/2XETK8RIXP2tINY0Ta0/YyXLON8fUhTspbYkSb7Qmyt/VBqljZWf4L3U
7yESmG1zOsCb6Z9z9iQ7PbBbv0F/8RTLZiFP8F7yp5B3rTnBS+jfYMqTLk8PumOxEB+OGlW/
xDVf7WRm1R9aEA+/VEP7mo4HCzjXrtX8PK6958qb/tCKenrXEf2bXR8KJUHVRq3qVvo3FpSm
y9LjVjxB/3r0tzbp3TR539hC/2YDIlMRQhR20pRUsFwmKD0wVp5fIWn+E+qtMjf/If2o4uOH
/v0FeoLiP6+snMwTvJn1heotJuuSB3gz6+M4R5PU+QDvZX3KpfbkiMQJ3sv7qBZIdpYe2M2s
j/zvTCpGnuAVrK+9GmKIU/iyqaB7NhXU2I8tqs0qZD0sJ2tNd7RkJuPBQuq/+SZhUJft0sM1
xfRx0m9+fXxdDFRjoZKtuGuSfk1/v99+3YzH2UF13udL09HIMN11uER0eTRaPB0QRcLcujkH
a9n2jUVdh/BSbOD7rRXyayrHjJYf8kn5otkV+rC+v0dMsBbGbNLvRO9v+upJo7sTvJf+Sajv
Jb/DJ3Yv+bN4XyWl7k/wZvLn1wpIavOc4L30z3rR5MzJgV1ALvClTWwcxpdFBd20EOHOlSzm
YyHbkLrGc+0xAPzyLJ6LBwua+Wks3SQt9o2T/gf/lfwNO8Fm14eaYhX21wRqz1bkV5BzJzOj
DoPLoOJWPEESRCSSZNVIksI/q5SkeUT+ZgMiqtj9IURuWSPsVSMnL7W+v99ZobhmVieWSl0k
XZOfWqEP+fujQoJUFJId9Cd4c3tfSCxkpxAO8Ob2PigCyVHNJ3brGvuNN2Zys6I8T/DeNeZW
uiS9x0/w3k8I4idqtsn0AK8gfC+dD+IAvqwp6I5RQAsBCe5+UPnlIxtTW5Ptk/YqV/H1RjzO
JcS/Kj+ABdKzGUtaMM1GuZfZeNiUxZe+NqNkv5U/tKKC2HQ0034ZU9yKJ6q1zAitqnWoSamD
VUKCbVTjnQ2IsPpliTvVJlnXgHhqCSUfTbVPr5ApOHmt0BggbYL38YxbQfj+nJBg1qX1AG8+
cc2ZkmZP3Cd4M+/TeLNltWWe4M3Mz8KwPZkyOMCbmV8v9LArSDG/J3hztwE+hH3T6jIB/nHm
d3lS0B2HgGB+2MWsVek9WVxva7rH5OUU69cb8ahU6ojawmM3q8aywlsoRFMG5/BsPGzsL1qk
8MBL6rwuYn51KF55OVLciic4HLFf2HyFEDSdR1pC/IaZvtl4KJpju9+fRLQmy2RbxGWmF6j7
VaMTRO4f8+KInzLv+8Rvt5YgR6ExqSpzgDdn+qAoZKc5DvD2TJ+/zW6ICe4d5Q2Fxa6W5XtP
8PZMn1nSuOYEb8/0cc8y0gP843zvsqSgm5YhrZtKQ+cUaXfrHZm+2XhUqyKSH4a1J50Gt2T6
ZuPhDuZ/fHnQkg4bWzJ9lyHFrXgemb4Gj70WEolbxQRf9l1+vREPYaUqlYGqYV577+cTfdML
ZNrUOmtvzvvStfdPom8B3/szYoJQGifTFyd4c4KFinCyT+cEb6Z95lwzqZBygvcSv1ZLpbQG
zhO8d5XDM5mzzjAHePM+lNIgneh7gpcQv0GDPV+uFHzTNaQBsvmxxdXq35Pom45HWcIxBJxf
YPKKuCjRNyR+0/GwqUJ3EtalJWcqdyT6+PKkuBXPI9Gnfs3gLuhM6Wc1Qu5k+qYDohi5aR1j
ahzz8ns/numbXyG/CfrJGXMdcmMu+T8y0/cjeoItaZbjuAWvpWWDJrsVBaGVqsm67oXenAIK
Hc2sw9kB3sxIe2k92Wl8greuM3KYvSSbsU7w1u+QupWedNg4sFs/H7IUq5Ic0T7AK/goDFzF
+LLN4DsmBvDgB8YmatKTRqWwhB400lcyOV/T8WBB8vPUQoOFkqYZuES0pD0sLV6Sg+nl8d1d
Y2Ja/LaQzH0vGZlxOjoQFeTLM+NWPJGHpKoSCi8xkbFXVNAGM03TAZGZrw4iq6gmPeEXqcrg
aKjpjRXqTrH9tSCPVORHVHA37ftDooJanm/kHPt7ojfngXpBTM6enuC97I+pJGtFgdzL+0gL
S/ImdIK3fntcofTs6O4J3sv8hONKkWR+B3gFU3opwBdH8WWcwXd8DKIJIhrAwMlfFcvlUWCN
AN9QT3oyntAG7AogzUAlKcCHawQSO74q2X6/sT4oBhRNYCI9meeCNT4gtQ6m2fnyzbgVTwgK
GqqEdklFysvVraB+j9mW32y4+wGRdbHGENPlQukWvZ/NFX+/s0LsLBa4hsEJpv2LP4KCq6jf
bkHB8IzA7Jzhid5eg7asTfAJ3s75VLLDjQd4L/MTKmDJQe0TvJf5UTixJhX5T/Bm5qfRoZP9
Dp/gH8/5XU4VfM+pAhn1MSHZrOV1ZVYwv6Go4GQ86Edq93iAtTJn2XnhFVbGhgNfh/n1CZ+c
Ts4t/P+kk34rmB++bA791377dTOeWqAjAJOvT+UO2ancFdY1Yyvj6YAeVsZAUVkPJ8WdNehH
9+ZvdtzMCrH64vsPyDTblvIRFfzHiwpCLyE1kSSAB3ovAWQo4LsyOZfwBO8lgCEU2JN9Gyd4
LwHUkCq74YMR4M0EUIphdur9AO8lgGqhV5lMnx7gJU2IIwJ4eVXwPa8KrGbdyRgb9mQmBpbo
vI2FBSfjCY3ACtGBGFK/yW2+RldQR6LS88tDXUgqKycFi9ew86fAyG8226+b0TwEi3tMT7NB
zc5vrZKUfinL+fVGQERkRlAB0TddWmRmSSLzpe7j91srZIgohk0Yk0KWH1XBf6SqoBSWtKrg
E7yX78X4cNZV7ARvbvGDyD9lW/ye4K2rHAPE3JNjMSd4M6tvBSW7ygd4c6spl5rsTzqwS9je
aOTk8qjgO44BD22ZZkRKVClrd71o5OSlCO7XG/GoQGvQukQSJjs7vWbkpI9GTmbjYVVzHtF9
k0N2dHrFJfc3LX6XQcWtcKJii6LhuKGh9J02qFhT5x1l+2YDIjCOhkV1BitpT5QVs8bt4QT1
mw03sULmt3wU5/s92mWzKzS15T58728QFbQC2ebUE7y5zltLz7pmPrGbSZ/6FTt72BzgzaSP
Stdkm9ATu5ny9WI9qWB6gjfvwVaSlmRP6ArCRwMfB758KfiOS0CLoYEq5oSvoib7ZduafNhQ
XGY6Hg3pxq41XEOSegSLCF9/2an4/UY8LOZMAphQmbPiiLyks49GF4zLleJWPMHdzEOpwDX8
av6eEePZePyWpCZWTWMsKk34lgypDMu70wvUoUuYhgA6I0/L/3zEZd4nfLvFBKVYVs3jBG9O
8GG+1HeCtyf4Ws+aBB/gzVwPw6gzyfUe2O3pPf9vlus9wdvTe60nuzZP8AI+QcPz97Kl4Ju2
IeA8xUlftCVlJUuWpCfGdG82HBXprFVimiMr3bBGS3CoHT0dDxsqijPyKLGl6d6aBN/vt9uv
m/EE3RMCfy2r/wfS9GiRa8gowTcbkEfTEPxX9BhOTrfz/XyCb3qFYsdZa2Cd1NIr9EnwLeB7
f0ZMsBXR5JjECd6cXNFSkzePA7uZ9FkJufW0lGCAN5M+KVFWSbK+J3jvGkst2Ra5A7t5D4YF
bbIs/sT+eIrv8qPge34U2KvWx+ih/5Sz+sSLUnwjGcHZeJRJwQxBsSV10uOhH0/xzcYTGr6E
6LcGoWRWflGK77UqyL/226+b8TxVQbqgsDqHTTYQbcnxzQbkVK/rQ/aIpSbf+6ua+Gh0y5he
IWev6HTSXwnN8m2W/5E5PvjHywjeGkBIjh4seFkuYMh/RtywcTHOflMnei87qXpDKvoAb+bI
vQglu/ZO8OZ1dtpmWf5wgLd+h9we451Jt58DvPUTYtcClizUn+AVPPnlpGbwlsvHg+/YKkjp
1XooGWntkvS98IdW9D7yyPdiMh4sBNhR1YkyZ3+JuMY3Rl/OUnxPxwNhCm/YGbEhZtPx/tAK
FoYjnnzZeNyKp5Xa1K8ynZlJkhKh/tCC9YFmIznNuXhq4Uqoxh2wOrPMtgqumK13mvzqhfD9
RkDRG2MY+qB+hn5sVrbzvj+kbijFFzxZ0j3Rm+viVGo2OfXE7iV/TIWzts8nePMqMxS27Fv3
RO+lf9gKJV87B3br5yNqBWuSWJzgBeQCYKA4J5eXh9xxVpBirQl3P0cUsrqS8dBPk7/JeJzH
OfcTiJnwxpidc16RsmoPD+dXZ/FkPOB37CiNi6pKNmPlDy3Yb2PyJ5eTx614gscxtFYrC0FS
zcofWuFJ91B3+M1+uxuP07im4js5ulSfOzpH/law2deugd9vBOTLYqAtxngMk2r3s4X+D/v7
8wKHTuQw2+V1oTfTPgtRnay38hO8mfixv6OSzPQEbyZ+XUuV3M/5BO+lfQqlZsX0T/Bm4mcl
K/l6YJe0Qw68leXyzJA7DgbROyINKnfSzknHM39ohVoPv6QVX9PxYBHr3Jz69UZ52rdih/+G
9s3F4wyu+78YKBSIKLnl4qEltG8gcCOXY8ateKp/NGJfGfHtDNWyrGJJQM1eKY9/vREQiVDr
/pKsDy+dLE1a0r3w0v36+42AUJj9jy8T+G8onfWbCujD+/4aeUPkEoNcSfp3oPfSP4hJ3ORL
/QRv7i5ozjmzHPoA713n1rBEf33uI57ovQSwS4Gsh/EJ3vsJqxXhpBboCf7psq9c3hlyx8ng
UfatrMJxNCff96vKvkMKOBdPsLlONVzGACXZ7olFlyhcv8zMfr8Rj19vKmCjVhsk0+H+0JrM
34gCXs4Zt+IJPYqGKqE9i6rpkZi+okzabJRqng2IDLQyteiNlKSvdzy1YoVgRAGnA4quyPCf
EfVrYbrf86Nx+DYF3K5xGGps2QnoB3Zzn18tzZIdYCd4c58fFIVss+QB3rrG/jsuLS3G/MDu
XWPuhSWvdePYvZ/P7zoKyXzkCV5B9mxUdrvsMuSeXYYgIwh2FcuK2Ycq54J4xAbzz5PxtGIt
RDqY9eEvkSwjLplV6i8tmb/fiMdvCkIC1nqHZD62renxw/Yqnn/tt18346klpp85pntEn3rm
KSqxYsONBa2nAyJCIaz+G2KAtD/LksaC3l9NqH+/E1AF66Ya1sw1vUL0sTNZQPb+jMChn6Et
96o8sJs5n5bKyVLHE7uZ8Wkhzib5DvBexmdQGlCS8h3gvWusLQw0c2v8xG7mpP53Zh2+T/CC
N/yja/zlGXxZZMg9iwzujWoIkHRoyctePLSE841KbnPxOH3zI6thb9qj1z7L+ZacwDqq8c7G
ozVq1SDNaUVSVLMtSVhClVGC77LIuBVPsDeDSq2ziHAyA1sXkVgYDHZMB0ROjKozWEKzZIks
HlqxQC8H1L/ficfZqy9Sg25da7bE+2ntW0D59kscMiVb6J/YzVzv0RWf5HoP7PbsHmpa6eYJ
3rrCBH79h2Q99wTvXWOLmbDknPEJ3sz2uEjyNXhgF3AJeNkvFmfv5Y8hd+wKoHRnEczI2gGS
I4jx0Aqu93IE8Ws6nuYfrRN1hla5WpYb9RX6hn1kHzYdT7RZVoLK2CV5v3DuuqT2WUdjQ5c9
xq14atFmFqoz1Riynt/+1IqxB7/8/3bD3Q+I1GrkYOOCwWm/jyXF3NftHd/vBOQvA6va2Exb
0uhqNmH5IXt/h76hZa3dT/De87bFDyZb8jvAm3nfw5Q2r3AY4L28T3sJ16gc7zvAW79DbFIk
y/tO8N592LVw9kJ/glcwP3qVFYuT+DLKkDu+BVj8POTaxVmF/6BzTCkeWtHG10dZvrl4IinN
flcJ71iUtLXvilpF6zqqs83F46S0K7JYfzplJOOpS7J8OGJ+l0/GrXhqsVbVd3IH65w1U6pL
Jsbhcd/9zYa7H5DfmmqYJPbQomzZrNgKz1dnfqMJ3umAKlgId6lUM/pZPZq/nfnhT6gcJinM
kvaZZfMl29UE1S/xyWLkhd7MR7WoJPM/T+xmNtqLZLu1TvDmVQYqrWYX+Qne+h1S70Ux2ad5
gvfyZaFCLSkadIJXsFEY5SEvHw+546ogxXmb/0GRsG5Ly8kssY15qVH9NR0PFqcE1Zz/BzlM
3rpwiU9v622ggDwZDxQKkWp1RurLlO1zWOLi4ff50e3ncvG4FU9zoiwVSU1AW7J5KAQIl5Ro
R22Gc/HUQr12vyiy362e/D2XtVvRtNH7KPE9G1CUJExChl96/rqAU+/gv52M/ncSE7RSs3pi
F3ov+0Mq0JJn1Aney/9CIZCSjjUnePM6YyuW1OM+wVu/Q65cgLJmjwd4L/9TJ509qch4glfw
v5ev+ziPL08PueOwIEVioNjpn2FHymXv/KEVujJj/jcXDxaQUJSprQFm6wL+0JI6tI7431w8
TuVYfYOLPixXsnNAS1raxvzvcvS4FU/wvzAMRCfo1CCtJb0kuzrkf3PxBJNrvjwdelOqnLZV
XqGTgy8vhN9vBIRhAhYdyERMycmmj6zMP1hOsD8kMbNygk/0ZuLnb7SW9jh7gjcTPy6Ynd09
wZuJn7GfJckm/AO8l/gRhaRV0kTkAO8lfgal96xBxQFeQCxQBoa3cplUyE0TkWiR95d9+BEn
dX39oRV5C4ZXROlrOh4MU4duzpNAuybbwXCJp0PTl+or39PxBIfjrv42a2TUs2X1JXJ1ddjw
enlU3IqnFjPw/yCHgCXVtKDgEvGVkdnedEDkW42ClzM680vP464oQ8Mw1TwbkB9K1Lv1cFtM
V6HxIyazivj9IT3BXnp2LuFC7+V/ZKW2nix+HOC9/E/ChzZb+D3Am/lf5xJjmFk96Sd6LwNk
yotyn+C9xenqtNOS5fMTvKT0O2gM08upQu85iWio4TpnIlHJdsj4Q0sY4EDebTKecBIBs65O
x6C2HGPCJaXSpqPU32Q84OSUuaNJQ2VMj4MvKZWOGKBeRhW34gkuh+Y3IgEwheQ1ahUDfEmY
vt4IiChSmdLCUaTlFsgfWjE+TSMnkel4MEbbiZz+NY8pzQA/48bvT6DslhPUEGdI5loO8OZW
v1DLSpZST/DmZj8oku6XPMBbV9mPjRKK98lC5RO8d5UZS82+Ok/w3k8YtomWbTo4wEtyfgOB
Gb1MKvSeSYVAN+Uq4X6aHfQusoIhyaj4NhlPK871lLRH0i8r/BgPLYjHXookfr8RD1v3JRIP
q2f7nNsSASC/0g9EBfWyqLgVT/WtY8BQWZF9kbaKCr72Wvt6IyDCSipViZQ4rzCzoh2z1sGw
03RAaKw9pDnJ/zeZHfhYB/+TRQUtKvxZ5vcEbz5xrYhiMtt3gDczPy1Us21+B3gv87OnLWSy
UvkE711liSaYLAc5wPvbTdPD7wd4RVscv2IWcRJf3hR6xykgTKGraoVeq/9JTlCVFfV1Z34D
OenJeJzEiTbtFYSVelqK7+eZ32w8zvyQQ9kX6nbmN5AW1MuZ4lY8weGEDSzEk6il1ZeXSAsO
q73TAT2qvaLQGD20dLJvBZVtozmP6YCwm/+LfY2YmqWzsR856QXMb7e2IBdL7tgDuznVB0WT
DSEHdnuiD7Lihyd4M92T0igpGXWCNyf6tGi2i+mJ3Uz2Ql4pOXV8glek+WxUaLu8KfSed4g2
soeEdKeeTaH7QyvIno3SfHPxhHcIkD0Sl5Q2bVwiYNL6yLZrOh7BmE8xDKO4JDdqS9KwvnN/
v99+3YwnaFsPtTvkmAlMJ5FWDEU5NxrdLmYDIqp+tagNsWpSomkR16svzcO/34gH++Oa1MnX
Pyvn/+F6/2RpwVoU09KCT/D27IrW9EzHE7yZ9pn/pdmJ6AO8dZWpSkFMViFO8N5VVoh20eQq
H+DNvaVaGLLK5gd4AbFoL9/zcRBfBhV6z0BEEbi1igwsSZO1eGhFRx+9qk59TcfjHA7ZSRL2
jqLJDrhVBiIv6+/fb8QjQhzh+O2Bs9Nii3iSjLLKlz/FrXicwpkaq/o1BqolA/Kn1gy/DqQF
pwMigVp9jVQwLc65yEGERg4i8wE5QQ75xxB/pLTFy1wLy9/O/H5EWtDvccnRiRXFlGXDJrtl
R0BLS3qin+DNVee4JWW7rA/wZj7aQwwsm4Z8gnevMvjCZTM0J3rrt8i1FpCkAM4J3voJka10
zEqXHOAFr5ahvKBeNhp6x9QglAIrNgb/4xwhd1NZJi84Ighz8YRSoCo237YoCNkZE1xhQ2Nx
er/kB3PxQKHa+mPc09INejCZGLojL6OXicateGrpncNXp1dE0KzO6Rp9Gd8Rv91w9wMiU/8F
NehVNNuzu0pfZshIZwMKPUu/oHb2y50kVbTq5E/ob2ek/430BZHCcy1LDQ705pRkD/HL5Evw
AO+lgOxfS0uKpj6xuwlgL5WyIjNP8Gb6R4UtKzJzgPfSP3HmnixEH9gV5G+kLaiXk4be8TWQ
ImJgxKD+TWpaW3BFk95QW3Aynoe2oJ/BtRsZJZ1OFmkLqo3SkXPxQNxhjYQbKGGSK8Fk7/8t
8nf5aNyKJ8ifLwzHALhvOssmu1ZoGv2G/M0G5OTPmqJWVrHke3WHuPR0QH5kNuxMEA4u6abD
j7j0KvK3W1wQW9GscsuF3sz6Qo0vSUxP8HbWp5rkpSd4M+8zLD1riXGh9zK/aMzMFt1O8F7m
p/6XWvLHcoJX9CCO5AX18q3QOzYCGjq/NYTR/C1vyRKJLsnDjOUFJ+MJpUAkCJMuIOu5QsYi
ecFx4m8unsjhMTZhIIUG2YEg+nlxmcu24lY8IRNTfctB2BsDJY1FFonLjHsQZwMiqoBdiImb
U9qt8oIwGnGaDQgr+Du1VxP/DSX7quKpD/dbxP3+jL4ghTlmckLvAO8lgOx/JyVnZU/wXgIo
rVTJDqAc4M0EsLfSNfsRT/ReAsgtNHWTPbEHeC8BNCkISbJ0gpdUfkfqgpdxhd4zFlHtZg1R
YnIyd3yFes4SAjiS/piLBwvFaazChFqz5i+TjVS3kn9z8UQezySGf5t0TZroLqr8jgng5Vtx
Kx6nctpbNxAOb5Hk63yZvvRo6mk2IHIG2Frk0FtLthos43+j3N9sPNha9dtGrdD8F5RdoI++
9IIhlN3qglzQkoNtJ3gv52tQpGeTfgd4c7ef/6WUzZwe4K2rjEqlc/Ied4L3M3vJavcd4M1d
p1wgK8fyxC5J+I1mTy6/Cr3nVyFgXLl2CCO0LJ9YpC04yr/MxfNQmKmRIGtSIdkwsEph5mU+
6fuNeFhNfYlUTCXp7tCWKAABtlGC+XKruBVPKMxUxhpmtVwBsoIsG7QFZwMijyZkHyuLX+DT
nX4rfkG9v+qV/X4jIDTSMMfjZs8kdo7wTW25D+H7G7QFtVB2huIEby72xo0vmQM6wZt5n/ov
IGvTcYD38j6rpVp2PuEAb+Z9vTidy2Z0n+DN+9CP1vQnPMAr2uJ40HZll0+F3fSpcGbBZoCc
rVMtkxYcnMOT4TiHCxVmpUZNpCZ7WcsKS0wnzoO8y3Q8rNFqK+CEtiflLOOhFXmxkbSgXS4V
t+J5SAt2xt4bNuiQpRU/Ly04HRBRAxNsERElU7E75GamA8JO0VXCCAY1mcP4iEr/I6UF1d/k
SS5wgjdn+rD4ay950h7g7Zk+yOvMPMHbGZ+0ZA7kBG9mfOQX4ezozgHenOlT5wjZfXiAlzC+
QW3XLp8Ku+kjosKPXh70H3Uyv1qWxCP6qnb4NR2Psze/REHv0LVqstTW1jjh2ZDyzcYjNb6o
2hCaZt8s/tCPU77LpeJWPEH5NAS/uQXlT+bLl1G+0R1jNiBCrMAeEyJAfrBjjY/IoJ10OiA0
FSR24ieIyUH/D+X7JysMhkN5ch79BG/OsWiJybZkjuUJ3sz8rCika7xP8F7m16nUrBfLCd67
ysLFt1eSgxzgzfuwl5r11z3BS5jfq/d8nMSXT4Xd8xER6o8iVQ/dh2yyb8VB3MQGE5aT8QTz
Y0WLEZWmSXa+ivnZQFp6Oh7xX6B19mCgJYui/tCKsQ6nM7/db79uxhMi0dzQGqnfNHp6pHfF
DPnYM3g6ICLfa5UMoWdf/Ws8g1vvAwO5+Xj8DljNyK9Pikml13+qtPQ+Wvf//uf/+V//93//
j1bripG4G6dV7hW4e/4hOfmw4EeygJD/CYFFBSl+5U/OWR7gzQkwKJA1TjrBe7cZ11Kzlfcn
dusaA5ozqew3eIC3foNCVJ4+pZlhjwO89xM2DNHi3CKf4BVknAbyy3b5iNg9HxHutTrhE1CE
rCzUEtM43/6DlsvJeHw7dKihDtLDAy83MhgPreBGI1O/6XicF+ljihdb1urSH1pi6oeDFl+7
bERuxVMLggk7d2USwbQ6Ni4xrnnZufL1RkC+Ps3flMaRVU7aSPpTa1bo1XXp+52AiFvF+CcR
YpaN20dccRXr+xO5WEU/pzg5fHuC95I/atGvney7PMCbyR/5jyfppXKC99I/4kLZ/rondi+1
ghg8T85UneCtn1CxlmxH34FdQC3aS2W4OIovJxG75yTCxiGiUat2p6lbqd9LavE1HY+znhgn
JQXVDkmRpnhoQTyqozzsbDzaIqGMSPZU0kvFs+Kq4VfnEfW7fERuxRMkjrg3CGM8Z+jp+u6S
gvVLpvT1RkAhfBlOPGIdkh6Zs0QprX35/UY8vss8JAilVdZ02/JcdvHD/P68smK1IEnJbNWJ
3kz60PdXMl31xG6mfFxatub3xO4lfNzKU5wv1dT4BO+lfMZFstbiJ3gv5YMYT0lehE/wkuL7
qA3uMuuwO9YJUaf1Wwe27jekatk2xRX2Ne2RHHl5Bs/FQ4WaddMmgLVxLh5aI6nT66u22O83
4hGOJkWsUXpPznHQGnu/h3z3b/bbr5vx1AJVnZSzYUWrkNVUhCXdBDpqu5wNyNfHfz4abcs1
O6haV81CjSZtpgPqathjsh8Y03rac52+H9b312gqAoVmTrK950TvJX8cFdy8qCLsnrqRVkCz
+b4DvJf+CZZGyXr0Cd5L/7QVv0Ini6kHeG83C1J0OuR6Wp7YJeRvYKZil1mH3bFOcB6HTQjF
9yGbJfVU1+jr8Es5uK/peOK7hq4qlZ0tYZYsLenxUR6onUzG49dDP4Nb80VCZ+m59YmHVpC/
l42K/9pvv27GEzTO3ydUnc1qheRtYxH5qzrqLpgNiP3uxBrD1tK7ZWujvCTlJ6PrxmxAYg0i
+69M2XaJOjmF9+F+f1JPkbVQdo7+BO9le42LZmV1nti9bC8EEpMNUg/oXj4vvUC2W+MEb/3+
kLBkiwoHdu/ng1pUkp/viV1R2W2jyu5lzGF3bBJaaSYVaiUkrlkr7bLC6LGJjXIuc/GEZLQp
dgjblKyr9RqjkaY0arGajQdIuzYnEZCeGAozoRUsQkdJvsuW41Y8YbCBUh+10Gjqy/K8OVuO
fxsZGvG82YAkdJv8YqHRGCvpYfEVtXd8OQP1/UZA7AQvDJMBfd+17ArNSXB8iN5foKMoMceX
na0+wHv5HpKfoVm/+AO8mfE5Dc7aAJzgvaxPpUCyqHJgN3M+50nZE/sE7/2ESqVpcpjjBC/g
FSgjFcXLj8Pu2CMEhWMCMFFomJxnbwWWGOYNZRTn4oGwe4BuypGyTDaBTJo9/Nssx6i/ajYc
RnNCKUxdKNkv5g+t0OhrOkrvXW4ct+IJXw1UJ+Tcuy9QthK6Yn1CaOm32+1+PM5htTJ36AiY
lwhaERC+VFr4ficgEeDOYaMpyffB7OD7h/T9SQ1Fca6evHcd2M25PS01KYp2YDczvf8PAAD/
/+xdbXLstq7cEQufJLEB/7D3v58HzEiTquSJB6Jp2rnxTd0kP1o500ON1ASBbt9eU1Itn+Dt
9T3QrM/PAd5e38sGpRzYzfU9zNcfn9gvr++9cjj6vRwO7L2KMreqnJ7cWFPfo5GDzhyfKNVV
JIRaYxg5eQSwKBdPRoYms3yoYq9WoVHP86EVTXzXsbt/3W9vN/lEpc4X3kVX979j3plvTX1v
kIs3TagigzWLgjJhcrZmldK7TMr8+AQhbTFSg9qg+6XZg9y5rsRfqfcDvBMrl9jrJyXfE7y5
vhfBItnTmgO8WfX10jlpNXKCN9f3/A+lbCTyAd6s+h5dZVnZ9wTv/YTm0geTc+MneEmFb/Am
tlcQh90L4iBA37zFeIBk+48WVfgqXSml92k+LnpMhVkaheVErpBNS4QFGg8qLtN8oreyN4WG
qlkv+SUdlq4r/ny/vd3kE9W6xnHHEbRuSbPOMHlZQeiyBvv+CUIVQsP6rwce+42dyg9HJ7vz
hEz8adDFatT5sie7c+1JP135cVr53XIkS3qRLXgoLRsq2W0d2Py1mew0OsF71aj/oZLO8T3A
e9Vo2AH2bLjWAd66yhEiFy0kSUX/BG/9Dv2tW4CSEzkneOsnFF846clfygleUocc9H3ZKyPE
7mWEaAwRA3NrpMl5BVxyoInaBweAk3weLSaILqQEqbXcXSRrYvva5XD0xzSfsENApYZhf9KT
dUie9PO4pUZfCSG3+IQa7WBdAKSDpscvlqjRa8eV908Qsu4/HrLIijTLarcVTUYx6/vHG+4+
n4qm6irU/AWVzSuY7Zv86WL0P+Ud+IgdTVoHOnZzJVIjRzzbafgEb9Z+Ukyy0xsHeLP264Uf
TV5J4+gAb/0Oaye/s5I+7yd46ydUbEU5mYRzgldUInGQ32evlBC7lxKi3Bmldq18IxJ4ifYb
GclM8pEi0HrnWjla9HKFLlkzY9J5YBw9yYcLS5SKRRVZkoW7uGiBtPA/9I/329tNPqHipAnE
dografbIdon2Ax40t04TMgZFcHVO4R+ZrUTailrxYwLkD3fcfULN+URR1W83p5RVs23qJ/Qr
/r7fPhDDIDhp1vtC71V+EpuLtH/gE7xZ+Wk8qbOe0U/wXuUnLjdbtovpAO+t+mktrkWSwTUH
eK/yAyzJUaxArqj3XVqFxTv4FUZhN8NCWvh4NLM4c0res5NDhH8/fZZB3+EkHym9ETTrkHYg
iktWnD0P379zbLgQA1PUx6xzslM4LlpR7YNBbp+9gihu8YFHr4N0dLlXa0v7K69odvAN7Ejx
zRKq5Ey4IWi4MKXPnpdIWPrzHXefkCBFah9aBck2usLkpulX8f0Y60CsxV8AaeH3RG8Wfq00
yp1IHdi9si/cADXZefjE7hV96jIk3cB0gPeKPpZSOydF3wHeK/pqKyTJp+IJXlHu49FR7yuM
wm6GhVR02cyKANlZ3LhohfQbZehO8pGiqqakjXr0zSfF3xI+/ZLPxzQfLvqICukaLq2c4+MX
LenTG/lG2yuL4hafkHHV1LVs69Rd1O60Dhw3Hs4SquDKjyMsrhkmm2hmbZb/Lv4uh/M/PkHI
n1ZISujSTxpmR07kd+Tk8yMnu70DbwQDn+DN3X0RB56c3z3BewVfWAJiNhn4AO+V9a5AKmcN
wQ/w1u+QtRW07KzJAd57HyoVTAbqHNglvX2j891XEIXdCwrBphECGqd52Z1UDCavEHx94BU9
yYdKnIWCGWKDnjdfWTJp0gcTn9Pr02qr2glRs2dtfs0Kq2iiK+vrv263t5t0HiPGAhU1/JUp
eai0aMSY8YrQ+ycIVSHiyt0eA7npEeMlB/DD3r5ZQnGs232NKPaB6RFj+c0FXqD3vmvEmLJF
qhO8Wfb1wskS0IHdLPpayfpIHdi9kq/5Gy49cnKAN0u+XjDbGHmC996DnQto8oV1gr9c9L0C
KOxeQAhGklp9NCRhsscKlwRQYOWR6JvjQ0X8VQXctIX0S+Ze+0Urqnx9EBAyvT5GvixMbL1V
ya7Pio0kAYya+l7xE7f4hH5zmSS9O6XohdtpIYiXhN4/Qchv4956zEX59indpbhE9eGlJ+LH
JwgpkKqxL5OB9CyhuX3Tr+r7Tg/BKJgkzVAO7GaxF+GlyWf4E7u9wkeUFXsP7Ob6npZeazYh
5AneLPZqaS2ZQHmCt9f3zJKToSd4STff1QFOvHxfKRR2MyXEF9ilhIBxT2YcrBJ7l+LofZpP
FOu6Eol/W65ic3z8ojV20aOCy+z6tNZdSTwGUvLT1StOXvyuGB3pvjIobvGBEll91KL5kRsk
4weXlfhG5kWzhKo8zj75WbtMJ+d+fYlvlpDfZ0i11i7sO8CcFvgt8f27XQRNkq4oJ3jvG5cf
JzfZudMneLPu66W2ZBD4Cd5c5pPSKTl3eoK3n+w2SrpZnuC996E9ehyTyu8Af3mZ7xVEYTdz
Qpp2A9d+Jr1tPtsdze7O8Yl8uAomWFkk6QqyKB7OLucEPj6xPFY5hpGBqEJydDcuWnK2O6ry
vWIobvGJeh2EE42Rb9qQ0iaCX1/lmyXkNxoThpwVpbzwWzK6O2wmmCWk/kQgI982CUO6bDnX
PvrThd+XmAgiJZv9acVTdtmAyX4bwSZJsXeC98oAbHGmlE0pfoI3y1Fz/ZbNKX5gt64xMRSq
yeHRE7z1G2xCpTdN3oUHeOsnFNCS9eI5sAseKmMbmVdUht2LMlGunSNBLGZX0yPFK/jUPqoJ
zfGRYtoxAt6YSZJGlLJEu/kbfHT+N8eHSoOqSGC+rba0ofWcp8ctC8FXUMYtPqEqq/8kejVr
DMnn5DIbmZEWnSOEBWKE/UkKs0X8FW3Hz9awP9xv99dH1ff2wFWa/4DShuNzg1k/XYn+pxwE
QZIprCd48+mzFcwm2D2xe2WfSqmWzJI/wZuFnxVRzQq/J3iv8CMu0pIn5Cd4r/BTKDGTkXaP
DvCSKuT1eSDCmZUR/3ZL+kkzoMYVDbNdsv5+WMBH7PpNPMvHf1KtOpn6iP+QrIPgil8hNr52
j57lQ8VQuFlFIl+obIqdLanatet+h5PP200+IeJq1dbR/G+crkIuKdoNzKPn+ZirWGEVtObX
ZkdmbMF+f5DK9/EJQhUVqPfu6985OSv56x797zUQJCkxdZ4sjB7o7cfPIMna7QneLvxa1r7s
BO8VfsK+686OXB7gvcLPwmEnKZ5P8F7h51+LJGfuDuyKil+/rsD4K+0lK26GhjTs3HsjVUo6
leBkUuk/Kn7XTjKzfLS4Oo6mEyVC41xBKS76ctk3x4dKrxEtqFC5WrIKHhct6dK7kkl/3W9v
N/lAQeuRT2PMVbIN5ItsBOGyb/f9E4ScBht3tW5KSbcBv2rBxokArq3K5wlxJQZstSPV5Ls2
LvqVfYtk3ze5CGpJWwg6dK/uk3jlpI2jn+C9uu/hCph1a3lg96o+5dKzwvmJ3av5mka7c07y
PbF7FV8P28zkBzzBK0p9A+NoBHppipthIS0cl6D7m6sm+6VWab7LcI33aT5SnEq31ir7/5NL
VPoSyTfIiZulwwXQmmDYIRomzRB5zSHiyDzw5PN2k0+It4gJ8S/LBQslw1wWmQc+5kD+cL/d
J1R9K0ahxw1Ie5bQkkhaS9xx9wkJuDauBA0QIGnhEVf9ar5PT5rsNg/0d2dyeu3Abu7oi61R
Uug9sZv7+agkX5iB3Kvhay1Qs27AB3jrt8fV9/89+UZ7YjfXl135QnKo/Yld0sl3NTwYL11+
iYh74SBYRWsMLYhAsg4WF63QeDbSeHN8qLgc6siRA86abArwi1asj9F1J9/8+lS26K1iiGnV
7FTJkmHV0TjxyeftJp8YJ3YJ7rrVhQRysjVn0TjxuK43S6hKtGsotOqiq6fjQZbU9XQk8mYJ
CYGRb5Aserjz8SC/57kLRN73jBNHPqFlHQOf4M1tfFQwHQh3gDfrvVa4pseJn+C9qq/5awGS
veAneLPqa66UksXHE7z3PvSdDnCy4fUEf7nyk5eyuJcNEsqPEJvrMMge6C4SfqO+qjk6VMQ0
qntKHTXZUr/IKbpfOl9/fGJ5GkOtXbm11rOpTX7Rkj6+kfCTl6y4FzzBoK6Qoatwl/T555Jx
Ypbr8fV5QlXVfzpMKihqaeG34sh95CMzT0hUagVVjpnv5ET+r4/Mv9I0sJakk9MTurm2588x
S7bLn+Dt1T20pNPSCd5e41PNhr0e4O01Pu7J8JcTvLnKJ6Ulz9UO7JKT3FETvb7ExN1YEAyz
3gitp+Qc/CrTQLvqOX+f5hMFu6i5uHC1ZC/iqhpfu/aHnl+dqgi+7uL76pq0U8I1FaRxjU9f
QuJe5gSZ67wGcVr4o0p8s3yqtDC/ZAtDnORDdVWJj66tiuYJCaE2fx5Ys9rSK/Rb4luh9L7P
MTCfCeLYzQW+6j+yZGDECd4s+cIC8IZb4ObiHhdq2XGSA7xZ7tWYHM3VMU7w3nuwYkS9J4vM
B/jLi3v1JSluRoJUV/Tmbw9/YVm6urdG8F3xeZ/mQ0Wcj4skA1ZJPshoMrX075IPRse6s+vT
NEqVEr7KLftcKSu8KYeRICeft5t8Qr01qmDqd7Pz2moWyDLq3ZslVMWs+v9cJDGkc9OWaD65
tHP8+AShGD9BoqZq1pPnQHHV/6Lmo68wC8zmXW0WLtka0IJH5QJ9/F0GhpIti5zg7QfgtSUz
dE/w3ttMoSBlmwoP8NZV5t5KTdrvHdit32AVLapJv+8TvPcThsl4dpdxghc8VkRHA83tpcBu
5o50l3YgbL6ftPR58QrfF70cx3yf5iOuwKIlX6Pmxsk0HllSdMNOo9PIWT7iYrJVV1/SLGlD
IEvO8+lRs/zD/fZ2kw+UyOGt4JvvSLvJyq8VResI6fvj/XafT+8RcKPcQWvSAtQvWmFjAzyq
ic7yMWqtdutae08PH9nU+vx0efwfcjAUf88nny4neK/yk0cnUFL5HeDNyi/sc7PjoQd46yq7
XC9JE5ZA7tVUxMV60nL4BG/9hB1raZBUfSd4xUG4jEaa+0tV3MscaYQCDaM4mo0gL0t6OJVH
LjZzdKQAVRcV4j98EU3e42XJNFKrI9E3x0cLNVcTjVsURZP1lLhoiei79kk/+bzd5AOPCXrf
TEpD7pbcZcCSEXpXSaOmx1lCXSzmxHzPRNaT3lt+1YqyKA5l3xwhDB+oJhKVXieWDlWaqlv/
yr7vNy9EK5gdgjjAm/UeF9RkE9AJ3qz3/ImbdTM+wZv1npWGuUPPA7tX8xkWzQ5gn+Ctn7A1
KNlwxAP75YrPXpLiZhRGbabA/vZgS7q++EVrTsJHzWhzfOTRpd86SuuamzmQyRb9v5+DD6dc
ZtlY+IlwAzHFZJ/CouAVsz/fbW83+UBh9cedVejA8PjGcufgS3o5L+233z9ByJ89FDsmqX7j
SbZVcImCFRo1284SipbUpv5y970GpQ3F51IAfxXfj/EtpF60Z88nT/Re6adUONk6c2A3dxJg
oaQry4HdK/tqK5Tszj6we2Vf941j1iD/BO8t9VWLkNRkqe8AL3gV02Wpwl/F+ArCwHtBGN0i
LaeKK6Vsix0VW3EgOjzgneQjfr8yx4u4oXJ2d1NWbA6xj17Ek3y0+N0N4tIPkDQ7jegXrSiN
4aChAF85GLf4xIAakCn13tA4WdGPq1aUxi7d/t4/QUhd8EEXguhVheyA84qoH+LLwPGPTxBq
0Dr7zRZH14BZQnOxiL/S71vtC2u4g+R+gyd4r9hDdYWZPDU9wXvlXhgTZrNdn9itaxzV2fQR
xAne+g2ySNHklPiB3fz5tDzzdFMf8AleUecb5dLhKwADbwaUCFX0969v7RWzBzlrIokv+9/e
p/lQEXRVxAhi2CXbn7hEjvfLoeCPz/AJtVdbdFm15BZjDR//cweVPnzFX9zi48LNFLqxQZPK
LSsm5ryQ/17pu7R/ef8EoYoui9gfQs16dg5uNsft74Tkz3fcDCEz31s6pWZS0wY9v1POC+Te
t0w5ay++4rk79wTvVX1hE5I14TvBm1VfK8m3zRO6V/NxKy2bl3yCN2sqKkTJ3f8J3voJfUtf
wugrV0A6wAtUBV8Gz8db+JWBgfciSipSIxcspJDO1SlLjHrqZTvS+zSfKOqDdagNBSVreFpW
jBTiw+ro8h08y6e10EfVXCGJZq16Vpy+E1yq8r/ut7ebfMIDRQWYyTUfNM2e78qKMQ7SQfz1
NKEIivYNk/9DtCWtTWHJL4ho1NA3Tagx9MrdbzjfaCSD62HSOPNX9X2ri2H3ZUv6BZ/gzUW+
6s+ybDPfAd5e5KMGeSfDAG8v81XNWgMd4P1lvposaZzgzZ+wFtTs7PMB/vJC3ysRA+8lYqiw
gREhQNo5ZVGdb/QCnqMTJS7s3TWfyyOuW+t8hgNnm3k+zBB+yBxJe2mnniVzrkPF94rDuMUn
6nwcXgXSnVC2sAxrzqnpcvD9/ROEKtYYcTWq1i058rCqzjfyrf4EIVMygapCHbKa/LfOt0Lx
fY+boRYTSdb5DvDmOl8rYtmAsAd2s+zrxXq2XnKA98o+4cKclX0HeLOo4iJZN9gTvLnS5zuK
ntzTn+AFukIuCxXxHn7lYeC9PIzqC1x7q0zSkhP7ONm2/fd2PhxV+ub4UORhAHRBIIJkmwUt
Mcz7Q6Vvlk9j4E4u+pA4++hbk1fClx7Jf91vbzf5RKXPTE0V4gwhbQiyptJ3OZry/glCFWIS
qkqovmppF+sVlT6Eq+Hqj08QathbU4NIr0w70Mw94X667OOvMDRMTsstyateNl6y3zpQe3JQ
8ondK0Tjz8R0ct4TvFeKPrwAs9bVB3jrGrNGfSJbPTvAW7/DhlL643w1cxse4L1StHOBbD7i
CV4hRWXg6oGvvA68lz7C0pTgUUXhZPskLZnxRO0jZTDH55FcI9Fp4togPVO8wosaDUdKdI4O
F3KFq4hWhdOGn0sGZVyJjnY+r7SOW3xcU3bhrl1bV+rJjO64aolwG1gHThOyTjGURb75qdDT
XnsrCNEoMnmaUK1s1AG5o+/pvjYK8KdL0f+WeWBNHnGc4M1lSC3pLqIndrP2k2KcNEM9wXu1
X+tFkoc+B3brN1hdKnVONmuf4K2fUNUKSnJ7foKXFCGvZlbjVfyK7cCbMSRCQo1NqWpNDzGs
ULI6HPGc4yN+v3J9yIpINsv6B8qKImS/XJ+PaT5cXE7EsHetRDUpLHhRiauPZopfoR23+IBv
xxW632oNWSw9k7HCb2vgsvz+CULG0KFiZ3RS7Wttlv9BaFSEnCXkeydnpMzcjJK7DZjcPf1K
v+83EASJaLLkWOyJ3qv6xJ8AlixKnuDNuk9L0nnpCd2r+Sy+kty74wHdW+vTXjB7fHOC9yq+
cCGHXK//gV2i90YeMq8QCrwZEuL/3e5apVn8ldR7umS8REYznnN8pPSOQGIo1VrSDCsuWqH3
RjF6k3y4SG/iL3YGg2xlzC9a4iEjo1LfK4TiFh8oHKZ35HecKz5NtmXDkvkfwsscyvdPEKpk
EgE7rXXKDu7Nuu39w+VntMOYJSRijyz1p0t5OkZvqvj/q/d+jH0gctHsjv+F3iz7WmnZZ8YJ
3iv7ajinZ4dNDvDWdRag4q+S7GzsE7xX/nEvkEx6OLB7C5JYi4Ll1vgEL5AX2EflvlccBd5L
CxHTKPa1EH9JizpakkGGKqPW/zk+Epl3oETRD61JJ09Zk3n3GC29fBnP8eHSqYbJhzirZAdJ
VMBXaAv48+32dpOO6zjGGC22cNyjZGMBLNkeu0T78/12n1CF7isPpJp9Zi1qOGQbNRbM0vEX
JqChxrxWdpodJreDv9rvW/0DfdebbZs7wZsb+8JkPTnBcYL3qr2HJ2DWcfsAb13lqM6mrcie
2K3fIGsrEY2QbDx8gvfehVVLdnbhAV2gJJhGB22vHAq8kwqARfz7A+7WVDk7VLzkXLdexmq8
T9MJDarWuAmTdcgOYyypW9qlEP/4xPL0sD81Jm3pcCS/aMHtRq5f/ni7vd3k45qtGrBrIpd7
LWsJ71ct8cVpo5a+WUJVBPkxYOJbJc5KoxWjA/5yG7X0zRKS1pr0ZuILVZMmI7NNl79a7weY
B1YsgD2ZOXmAN0u+HkODWcn3BG+WfC32sFnJ9wTvlXxRmZWkJ/MJ3i76IkYgLfoCvPc+tF5q
w6RuPsArSnyjhFZ6pVDQnUyAEHEPpxJXFS3548c1eWpDN5lJOmEMo34NV23OZ6f7CtoosmGa
D1CLSRvDrpT8UdCSgONxSAi9Iihu8XmEhNSHjPXlEd4aEgL1Spm/f4JQ5dp9efzHg/73bP/b
EuHHNCjyTRNSJm4sav7ot+TbNq76FX6fFn67/QOb75PTISFP8GbFh6VmD9NO8PYiH2U35E/s
9hKfJJv5Dux2tSeQni1+greX+GrNzjoc4K8u89ErhILuhYQItxrudADQ0iEha+p8NpJ7c3yi
ZOcC24URUNdkoNWyOt8gsmF6fXoNtxXuTRRqMmqy9BVhzWaj3cUrguIWn6jz1SbQDdR/vOkj
0CV1Ph6Nik8TqoLQ4iypklB6dPfr63zThKRVJYPWoblAzq7Qb51vhdz7njqfFLSkKdoJ3vvG
Zd+RJ0ejDuxmzRdW2kkvjxO8ucrXCqXnMw/wdt2XbpM7wXs/IbSCPTmbfYIXvIdp1FdPrxgK
uhcTItUf770bqaZTQmTFaXW9rIq9T9Pxnzyw60lp+PSzyBX5VrQlGg9Od6fpQFVmV31syaZE
v2SN5ht08dErgOIWmyjWqW8uXH4Zk6QDKJYYRiOMNhmzhCq7jEVwJSvELd3Ht6QIO2obnSak
IlJZGVVcl2dF7Nxh2k/XfF/iHIjJA3NcEcjx7/UO7MV/VUn/mAO8V4liJLylI3af4M1a1KI3
KKtFn+Ctq8zhq5NMWzuwW7/BJlo0GwJ8grd+QqFaTJPmFyd4SQVyECdBr3gMuhePQS4P/M1j
QqjJPZRftKbT8Kpi9z7NR0qEYqgScuTGJq3Gl1i54SNd5FIbzK5Pj4av3knNZVzWlrsvaAjw
rfxIjb7CMW7xgcfOh5urHNdwWZtVWLL3IeCRGp0jhAXItwnkTyJfpWxSqV+0YoHaaPMzu0Aa
JqINlABMkr26s64TP12M/oe8A7mwYtLF4wBv7zY0ydbQDvBe7adSGiYPiZ7Yvcqvxp4xOe58
gvdqP6JiyYyVA7tX+XUqnA30PsELlIWMoorpFZBBNwM/GASlNU7/8GnJbKdve0bv4Tk6Ump0
GJohql+Ze23FRQv49MtG0I9pPlwQO2DFRtCz8d1lRV8rAY5Onl/hGLfouIKzSKgmMzIEyw5k
LLHGGZpGTxOycGHyNXLR1zXtsWwrCDGOTp5nCdXwFQCoFsPeyXbqX9Pof7VzoCRzhE7w9nNn
wOye9wBvV3ydkgOxJ3iv5mtatCW/wxO8V/MZlJ6uOh/gvaqvWkFOvoNP8AJZgXrVMBXv4VcY
Bd3LChHS7h+yo4BqOt53heyrwwawOT5aEFz1tThIt5qclPaLlsTWXTpgf0zz4QIMhNhcV7R0
hveaARO6jF/+6357u8kHCruORe2goJgd0oIluYL0eDL/4Ya7T6iq/8XNqnTIdjvMyqR/eDyO
Cn7TK9RNwW+65rqckj6ps/0Bv7rvxzgIEsSLKusgeKD3CkCJCZKsIcoB3isAKxbmpHg5wXsF
oD2yy5JFvwO8VwC2VtSSk3oneOsnVKLieinZonuAVxz4XiYexAv5FUlBNyNDuJKxRiaZWVoA
Ljnw5YGn2ySfsLqy8CZmMKw1mxa34kk2Toub5MOFXJj7/aMsSMlfBS85kCe4rJP9db+93eQT
ZtAU9t4KMQGSLDQvspAeTxjPEnLxxzEGrhTOe1utZWBY+JslJNTFdxsGDxfBr02W/hWA32oj
WEvLNn+d4M0dfrFVSg7wnuDNHX7kf6gkA1cO8F5pb1agJztRntit3yCHWVF2kOOJ3b7tSPeO
neAlp7yj+ssrkYLu5AP4jiPmMrQThZdvdoJ1yWxGvZxgfZ/mQ0UZ/KlkAo1qy05nzLlh/P2Y
93I64+MT6xNzM75GvjitJt+9EVGzQr5eHsP/db+93eTjwk1bdJD5Rg2rSrqatKQ8Vkf1vllC
VbpYxSiQ1ey7M6qEKwjpFaGPTxASFpd5KL03sGRI+6/c+zc7CVLBpFfVgd3c2ffoQk+e8x7g
zZqv+YY0+QlP8NY1JmilJlMAD+xmzadFena++ADvvQurfyuadEA7wSuKfDjq7XsFUdCdZIAQ
cPHK6tYAMGkigWtydOulSnqf5kN+O0BrVs1IW1LF0qQpxj98ZQY5cdPr031VEEMphUtx1ldm
ydAADfyj6ZVEcYvPwz9aGJhjaCA7pL/KV+byUPT9E4SqRvNl95uOKiX7JJapvlFZeZaQ+PbC
94Cdw18mOafy6yvzr7QRfKRs5X6DJ3hzkc93sMkC1YHdXuKjbEvaCd4s96Bgdg76id0s92KO
LCmmTvDmIh+VXiFb5HuCv1zuveIo6GZaCLiUiPnDHs7Re+XeyE9mjk/U63wj2tmkgUD2jHqF
uTyaXZ1Rf3xifVqoV3U1zi3v99OW2CIOi3yvMIpbfKLI12v8BcBi6TCKNUW+UVzINKEqFSVO
qB9jr1uLfFxHG4xZQsKKMTUu1Thb94fJNo9fufczbASzkuXAbi7y1Rgwyo7vPsGbVV8vNTt9
eoI3qz4rLfsJT/D2Mh9lu7xP8N77sElhyTYYHOCv1n38SqPgm2EhMUrJvtS+TbJc79sy3Tcw
b5nkQ+HXpEKNI+Eqfbi7xBexjY7apteniwJhZ0D/t2wZdol5i6uYP95vbzf5RMEOXe7FJG/D
7A5+VUzc6HB3mlCV5rdct8ro2jynzJfpvis7p49PEJJe/T/cAPym47SQnRuz/um6j/71VoK3
RhGSQwgLHpYLVPL3GBzW4pui5KTBAd5+FM5pg8MDvFklW+nZg9wTvLf9EbqUxpYss5zord9i
ra0YJr14T/DedQag0inb53qiV7RB1kHQCr+CPPhOrEIrUWZB3210FU6adbRFNoc2Ei5zfCIY
qIII+53LnJzukkVK+ZLPxzQf3+4bCJJqFZKWW5+4aIWwvLQQ/+t+e7vJxzdZFmnXrRH5/5NP
yzVuN3A5NfY+zQf8ARRR5KTmOjntIb6iLdr5DCry0+vDHcx3mvIYTc82YMxNRv50mfwfMjnU
0nrWWvgAbz6VxNI0+Tw/wXt1gUqxbLPmCd6r/6hB8QdV8iOe6M36T0tPtmgc2K2fzzhEcbJa
f4IXaAu6zIuId/ErzoPvxCv0gtalgX+HKEnvxl5oxYSFwmDgeZKOFLJWu2mUeTCZHC6FV/Bp
9Wp5Pqb51AIckeECvn9I+jbWNYY3yIN5Z36Fedyi449kquzbNRNzpZwe6FkSTjJUfnN8XMSB
WFdi6f5DTxs32oL7jaANjsanF8if+Nxb7KgrJVvm46Jf6bdG+m23OaSCPevRd6I3qz4umHxU
HNjNmk/9pZOt+R3gzavMFsb1WTejA731W2zoG4qWtVg/wHtVX+9FsiMwJ3iF6rscsYj38Cs4
g+/kGLRiHbthM5dKloxWbmuCQIb+1pN8pFToVn0zUJtCco38oiVGh30wkDDJpxYOAz0jfxtr
TTao1UUthKNBe37lZtzigy5JEX3pq2DMCidlxRIdy320zZjjE4keyiYKGNq8po/Gl+g+Hh2N
zxLqRITNbzv2f9OskJ0buvoVfj/G5xCxhCNSUhkc6L36T8kfbNmetAO8ubkAi2JWRB/gvess
rphqT7bwvNCbFWC0ZCYPH5/YzWe+5I99zh5XnegV3ZGX3YTxRn4laPCdQINeWtXovAOwyGpI
Fv7aikSQ8ZnvHJ/HmW+EnLicVdas0+GSM98+cjqc5ONiDnvtWEWp9qSxSl1kDNgHESf8CtC4
xQdjys5QmutaVzDZM19cMgM9VIBzfEIBCkcfbrTwVM4mnMwlwf1DAQ6MDqcJdaEaxlGqFbK1
2bjqVwF+VgF+g9Fhp6S59Qneq/miwAPJJrUTvLnTj1wiJW3wTvDWVRZuxXVm7js8wVu/Q5Ze
rCcndk7w1k8oTYv/mcnv8AAvUBSooy6/V3gG3wzPqBweJMoRnJa0Tl6Rd4P1smLxPk0nXLe1
aatMLvssxydmaFYIvmHT1ezyMEuThq4pSDT3+uUlkYOuJ0aC75WccYsPlNbFutWny1JygeKq
FYrvck79/ROEqt9pLBD/iHS7bM1vzQqNFN8soa6irvga+TawYZbQ3ATWr+L7CV6H4YWf3Hyd
4L3CL7qlJDsIfYA3C79W9JE9kXQ7DPDeVUYo0JLi+QTvFX4KxTT5HZ7gvcJP44Q5e5B4gFcI
v8sXV7yJX6EZfC80w4USdwrd14Vzc6m8pjRWaWA/N8mHCrfeoQpVF7NZZ9TJ9vR/jHeM3sOz
6wO+NzQwVxecXh742mmIv263t5t0ortNK7qmjDl1Sx8l2pJQOxmkKE4TqsRgzsd1OQKlQ+3W
zHcM0rOnCXUwNMGGfsNZssvPr5paoV/h9612h7WwJJvTTvDmUl/1HUVyyOgEby/1+Y8/b3gY
4L2lPtGSPPEK5F6tV6WkD3xO8F6tZ1iSLUlP6AqdN2zqe6Vl8J3sAi7IZBbVMDNsWSGBS9KL
bfTeneNDRbVbB7LwOUxX+FY8HbDjqMI3uz6RH6bqoqizQe4Hy0sqln+o8L2yMm7xCRnhG1yJ
jnClms7K6Cua4FgGzprThKpKdannu03gltZFa3ythxW+6RXqZKhNekwR5Vfod5J3gdD7LqND
saTF/AneXOFr8RxMFvge2M1qzwqkG1QO8N41llaoZtf4AO/VfA/XmGRD5AnerPmkYM8dsh3Y
BaqC2iBdgl9pGXwnu4CLC74YDlUUrcmqb1y0oho2nOCd4+MCrkeSKzfkanl76xXVvfG57uz6
MFZtER5bUZJpM7ymkQ9HkcX8ysq4xQeK+V3WfHVIGmdzv/2qFZ18WAehidOEakeVHsMPJpLs
hY+rvlz1zRLqTZ2IVRKF2tKdfP+Tqo+/wuYwOfCzItX632snaC4uk3W9E7xXiVIr1bKDJQd4
rxZVKJCe2z3AW1e5t0eEc9I35ABv/Q4bQbQxZG0tn+C9n7BqwZzOeUJXKNE6UqKvIA++E6ug
paO/dpDDqY6SHfE6ear0dy+Zy3rq+zQf35ZY71UMY0g6O1GyorqFZqOJktnlAevQgB+nzckw
Zb/dloysDidKXiket/hgQVc42shfHK51sv7hK6yLBsL6fZqPS+Tugrpaj4EsS45k+VVLGgEu
h74/PrFAECnKKugbhfRbrMBve+Eqwfc9NoLRmf3/1s/+DwAA///tXWFvHLkN/S/pZ6uUREpU
getHA/UWLYr+AvfiXANcnCL2AXf/vuTuaHx3ycgcrSwb7fpLYvvNerialZ4o8r1vrGcLeHIG
klwsxqL+Cp7M+7Sw0ZqDXMBTR7kguRSM3qwVPPU9lL28y9kqIr2Ap94h5+TYqh1RwSPOnqnB
/XA188A91grJea8agplkQY7GehO9aMTZs29wv8548GixjUiAIUMxJoqHSBT7vDk+h+545AOY
kjYqx1AwJtvxCw3JEjd06p6et+ud8QiPK17oRcqMHowOxHrRiKNnaCQhO+MRGodMWXYaoE7R
yWoeU4YcPW+y88MZA+SLfHCydv7kBFalxz52fiF/ry8kGMBZW4gqeC7rQ/mbYGV9C3gy6xOq
SWAXElTwZNanRcDGupgKnpxLQ2ecPE/QyYyvCBE2am9X8JBsX8PEAVdTCtxnSgGUgDEJKzUf
MqVB/cTY6CfujAddkWmJE3jhRyFaGd+Ipv5nGF9fPMr4QvAow5MxG8/R9aKXrjbE1ZRiVzwy
IWdQp2giEGph9CmAIYpF7X7i7oCSamFHH6NaEZuPaYf0E3vYmhEO54yQ9mNFGZ2QSzI2z+lV
F843iPO9joZgDI6jMRe0oieTv+xyNM4ZFTyX/CXZ/FhrqCt47jjLttRZFeFP2LnUD9UIzqjI
U8FT77BwcWrmYFSQPoFHJPyw4RuCqzEF7jOmwMDMBZEjeTP9G6HN3laQ7oxH9gIxM2hPZMZk
7PGUi0YkZPOmee/hjPHxEUn2D1HGyHrYkYY0AzWK2p6et+ud8ajQHBQqAMfDazALFA8YoBBa
3U3dAcm2KSU+au5pbaiV/o1ok252FfePEAQU/ochqZWQ7ZHrbQe60L9XFRDMMl0alXAreHJt
HzhiY49EBc8lfKoJWIxmxhU8dZRVcS8no2Z0BU99DyMVx8kbBQQX8Nw7zMnFDMY7XMAjKBK1
Mn6rKQXu8QjQUg1UaUIhz1SMXld60QiK1Cq46o6HgmdS4y7NYpo7TUaMD2OL8vXGIxSWhIwz
+5CMBYthCIUNx8Xgmeftemc8miDTPgahxyjDlM26K0M4bH7+gesICClGlduLarY9tb/4aFb+
zBPXEVBGNQoOwSc0zsPQWVVwYXxvQUAQHGYjaangycSPXbQaXVTwZOKXXYxsFxBU8Fzix1lN
6qztuyfwZOLHqtVgFRA8gafeIQbUNLfRgHYBDyAWMbWKrVYvCtxjDSAcIXCKTCkk2c1ZBfdG
rMM+N4uteuPBiEe7K09IwWgtOSZ3mVsNn93xMMeYMnvhfmT0Cgmd/Z5fdeQ2WoxxtaLYFY8w
hOLB5+yLLwWMRgV61Qgm67eY7M05AUUJRJPlFFIy6g7AGGrezvX1BpS1pd1DEiorzNws7t11
JHRhfq+qICirZzZ271TwZMrnnZEKnKDT83wBjJnICp5L90hd/Yx9CBU8l+4leVusJwoVPPcO
WU/kjRujCh6R52suv6sTBe501khF7XQJinqBWunRGEWZVmVfbzyEKlcCIao2ojXNN8QoJG2d
VB/OCCcJ0ZOlN0Qib2yzDmPkSrzfGp6nx+16Zzya5mPMJZBHVl2ZqWm+zaP3m3MCQo6IICth
zGD0NxqU5vOpYQ7cH5AKTOlZtXC+aPSm6VXIubC9tyAjmBxb2/gqeC7pizpFG+vlKngy8WPZ
JRmP/ip4LvErxUEyZiIreDLxy85YR3yCzs3xYdKZ0TbCFTyAVYSWOxyuJhS4z1RDbk5tARKV
DGwVWx5CYjO0FuHeeITEJoxqfFLQSCpGkdiWSUhnPNEBhAKeZGwgstklZIjayaa/8dPzdr0z
Hu2vQ2Hk6koTIZvd1PIQOZom6+sNSFgfMEatkQgZJ4tHt3J83SPEDMEXDAC+GHus5aquLOxb
Z30vIiPorWbyQ2zkh7WZzBYSZMdWk5oKnstFfXYYjHX9FTyZixbHeYeotYLnjnIJzhuzpAt2
6juoDSOy9zXe4AKeeodJNjne2LiwYEecN1OLG6xGGbjHtoBcYEK1w2VZ2Ixch4aIe/hjJ/Mm
NeiLB5364ArXSSV7MHYo4RBhN+GiDWG37nhkEpOZljxR8cayL7loiB8atzKQq03Grni86qbm
TBhSxIBWJcFBDnytXqbueAIVkrGPBFa5AbnoxY2KO+MBJ8MTomwYYikpGsVkVAb7f5GJ/h8p
CXrdJFqVBE/gySfPxa4tXMFziZ+KA7Kx/a+Cp44yU3CA3qiJsoDnUj/ZU8jW2b4BUfDcO6Ts
IGfjJ2UBj0hExlaXyeqXgXvcC8gRYM5Amiwt1iMIuWjEaXqzsbgvHtRpKQbhFrLry2jVlRmR
5/KZW4txbzxcZOCLCi9TNpJzvWgAuTjK8jzzvF3vjMc7nxATMBXInIwKZm7EHNSWke6MRwWh
yUfdaJTI0Vi+4cdkipsy0t0DBBFTTkTq923W+e5jsxfy9/pKgt67QsaJf0VPP3wGo2XDgp3P
+oqxv6yC57K+hE6WEaP28QKey6kKOq3gMWYkT+C5d+jZpWT8oFTwCNbX7PVczSlwnzkFcY6y
vZeFiwNbvUNoSIoMWqyvNx4fijBYkKWY2aiNRWO8mMtmy8yhOx5VugnJ+0zInIyL8Bh5HGFJ
Lda3elPsikf1Z2OSfUYKqrhszPnpVQMCanoXdwckBMmXCJ5lbxftx88jeGxsCkj3BkQlFHXm
K/oJMi4V0DklXHjfm1ET9NGVZD4YX9Bz6R96h8VoFFnBcwmgCgRma4/xAp46zsUXWSKN9ZsV
PJdesUwmYFsYFuzU+2NVLQJjl3YFj6B/m6vXX1QcptIL2mlPUQqAD7J+ZWtMNCZJlqhRDNYZ
j7ZzFwLvoyxisVjp0ojPYNs7rnt8gDNFjAQUi1Hmn0adkDbEpGl1p9gVz7F/1WvbSfAIVi2j
3v7VrzqMt7LmN2cEJPy8qOqeMtpgrDof1GEcNvVFD+cElFWaKaaI8shlszzipefk/J6T2WqC
5NDYE79gJ5f36cNoLNup4MnlfSrRYXVYXMBTxzgGlQc05qoqeOp7GIUFW7POC3bu/QX5m2wk
zBU8osDPt+je6k1Be5wCgotAuiCoyRob6YRcNMQtrjQEZbrjoUjCJki4BLOx4ErbkkdkLzfp
+OGMeAKhihIf6/yMtRl60Qh2FBoCRrQ6U+yKR7NCnlUMO4dSkreSiRHp5RA3hfduzghIm/NV
ZpnUhCdPbTEOmyWyh3NGKAvbA5kRQkJ7iV/fFHehe29BSlDzYsaNSgVPru4LzmdrW8cCnsz7
ssNj/sIoJajgubyPZNlOxraJCp7M+9CRMZe7YOfeXyaXyfgUVvCIWrjUSrusphS0xyJAhpeL
1vJEL/zPKI4oF4055W2l+Xrjwaz9kaQWwWQ8sxjUZHzUON1chXvjIWQokCAUtDa2j5HKaUvL
0GpJsSselZZRRWx5bShClawtrC8vLdMfEBZ5qxLL4xzY7IIySEH6+SeuIyDZkKmOoI8xFjMz
v0hID+B9s4UEszNPkhU8OdHnHVv7pSp4eqLPG8WtF+zkNF+U1dobFWUW8GS6F1y2pmgqeHKi
L7psFjtcwEMIX2sBXi0paJ8lhSphqHsHEwdjQapeNITwNTp5u+NRf41QhPAxmIWwh0gJZtiq
ujycNTyJ9SukmIwqvnLRCCnBkBsiRrT6UeyKR/NBEPSRg3LUfHzRLNKuPF9vQJrnE+aKQS1j
7A4bY/J8WyN0OG+EGFLh5JOMk1X255LnG8H3XktKMBjLURfs5CxfcsWqd3bCTqZ87HI0UqoK
npzjY4dWq4sKnkz6ikNjkc+CnXt/nByycWtUwUMo39aOXtfg1YyCdpprQCkBvMqhZfPZIY44
282brvY358TDGDhmLNbCRL1kRIYPW4V8vdFQYdlXJz3FY2NVVXBpiIzgZp/N09N2vTMezdWp
+xBrVjlk4zQ5KMMXN+vebs4JiALJ4EhAR3uaNyMe3R8QB4rkJayUvNGW8E0V8sXfETnB/fql
PWAWfr5NCzdvKuE5NzXu79UB+f7z/fuPjx8/39/+eKUPwO3jQ+uX60A+3n754e7x6svt/Q93
V0Ixv9w9PHz37p//vrt79O6v8U/L//6mj867X7/ij5+/XD3It3ff/OHV3f3jl19++7jIA/X0
AJ0enU8f7z9++unT04+PL/Hduz8A3JZ4FG40v7j//Yuf3suvX/vD8WvXa39947c/f/vGP3wA
+TqO1Tffqz9uj8n54/X3dbz+cRmvCePV+OXDbz+s9QOvU8D7q7uf/6PjJvgH/cPLrPsgP7x9
/6AD+PTDf31+/8vTd+8/f//TJ4lYJoj7R/n3z/8FUEsHCGCxhN8UsQMAmJlEAFBLAwQUAAgI
CADju0NSAAAAAAAAAAAAAAAADAAAAHNldHRpbmdzLnhtbO1aW3PaOhB+P78iw+sZijFJWpiE
jiHcWiBgm5vfZFtgJbLksWQM+fWVDWQSavdQsDPtzMlDwLb07Wq12v12zd3XjYuv1tBniJL7
QvmTVLiCxKI2Iqv7wkRvF78Uvtb/uaPLJbJgzaZW4ELCiwxyLoawKzGdsJpFyRKJCYFPahQw
xGoEuJDVuFWjHiSHabW3o2uxsN2dDUbk+b7gcO7VSqUwDD+FlU/UX5XK1Wq1FD89DKWUvg6M
sHeaxYNlSbou7a5fR8dXpyq2X2Ws2P77G9PIhfrBDofl1+/2a9l9FBGHbmSbq/3tSNh9Qahc
WyMYvlqtkDTv/ZwpYsjEUPEh0KlXODzkW088RIQX6tJd6WeQ3wLuwyXPB3mGbO4kQV9/kW4/
XwzfhWjlJKp+U5Xkm8qpAoou8IqI2HAD7WNhMEzepniOcBl/e4rKMOzZR3oy7gsfKNQjjyj/
lqYR6JGeOhAm+S9F30/RHAh5+QQXbAY+o/6IMsTFCZgnmvu8rXyPvEhCrlyfbJv32F3qoxdK
OMCahxEfUBseb4BD/Qu8HPocWXmhH2l/MFGWp/St/jngKxZHaxijq4CsUswjnwd+0DfjyHWA
VdPCyoW42UbwA2qDck7dDIENSl1doGTq0RHoFODgGDVWtCydawOwglF0/SX67ZngmkPDjo+O
A7dJKYaAFOrcD+CZh4NYwpjQ1uGGPwpqscQ07MMVsLZpspYAsxRhCTffJqe0x3EWOfUcx/kl
JYHtEsnFcc7yKcYm8FM5Q+Xz7ckZ/X+HTnPoSEBDcKfnkQ8j6nGGw50ixoA+jfVn2Z+eCH9I
eV7Q+Rz5CLVJMfUT3UW+rcjyzW0G25qDUbqACc0Dl6g07EJgi1IoFyFxIBGRJgf0HnsMuCgf
obZ1TYqZBo/zeyZCYo/vCvaAIwYhomOLRIEz1Z0uOGQ9phHg6VQFjMNjp8pCwA5YrGlXb+Um
QYVMOFdqaVGWP58Z7Y7hE+uLS+G1wLTRGrFU9TMCT1b+XNfZwSsbxLStoCI+Jegl3Uv/bp6z
r+uTBzDIT+/d7G4EPoi86XeaOC3XhCL4ux6GG8FzkMfbgvPkEOZiQQpDgOQvpi/M8AFiHgne
Thi0fykjwyCUcZT4kMSTa7TIkbh8CLHIkS3my1lGoryKthXy4LhtYAIGb68biAB/W6g/j7v/
liQbm+50C2YDPmkNB319ofypf+PydDx58brG7AZbLn7qTxsPelOSE4bOFGWgsNXrdUtRHC36
tMU/za0itdOWFpqyaZKGWPuNZMx7VVWeBsb8m7fYlsdjKeTDlbcWcrBJVMfu4LX5VB6blW+S
5bY9W/GezErDM+aD6mAsvssbtpireDQzHLM7xE237Fiu7Zmu6gAyfbE7ZYEzrg6aYdh/UNhA
iecIfBVbXZWO9J4kdHkxO1PZmIVV8Tw0OsazMTe8hTw5yIjH22Lthi6FTdwYq63hWuiHYSvS
sfV90mkTYzr0oDu5HetjRWn0lLFUHU5a7clcUqeT1qY9a1eHuqS2H8JGy543mDF3hqas4scn
b2S4i/s/kpUJwsHBRot7BypcJpfkZ74ayJ+y5l3aKp4Xpzv/AXDwAYkiS876cbSyT4GtinxB
BTfIYZOVgNMmwFaAAU91ogtpTV50RgNrqDuBaxKA8N/UH9lnu6G4SOkzdiCBPrKKo2a/eCbh
2AsZAQ/6bZ+6ibk1g11oOsAHlpAUkX4fsuioZd6A7CPyPPFs4aPpr5/ObJjm3VGKvHS6e6P+
SJqYsjxide4dkh77Dn0Sl1ujgFg8AAnv0LIQtNvlyGF1KIrIXKJSjz3sfwShCefNpWWlYFH+
x0fwGzWbgFjwjAiVWsWXfvpNRint1yr1H1BLBwivI3eXcwUAAO8iAABQSwMEFAAACAAA47tD
UkFRsCC1BQAAtQUAABgAAABUaHVtYm5haWxzL3RodW1ibmFpbC5wbmeJUE5HDQoaCgAAAA1J
SERSAAAA7QAAAQAIAwAAAGg+AVUAAABaUExURSQkJC0tLTY2Nj09PURERE5OTlNTU1xcXGNj
Y2tra3Nzc3t7e4ODg4uLi5OTk5ubm6SkpKqqqrOzs7u7u8PDw8vLy9TU1Nvb2+Pj4+vr6/Hx
8f7+/gAAAP///+z12t4AAAUWSURBVHja7dxpc+MoEAbgZCwQhyRuJLr////clpOZyW5t1Sie
qj3ilyQOPhr0ABLtL3rhZyov0EILLbTQQgsttND+W1rqv9n/cfyPtLu9/1v//Op6vYEY/1mt
W6p3rm9s+rFGaz8x2MF6O6wN/SU0Y2o3tvDifH1Jv4qU7vqardljWAZb3pyj1Tq6spysn/fd
2kTWub1a2+VJvKrVtXjeoiYdYprGsV9fxoqz3RtNUinHrl0haYvWpK6ELiWP4mOcD1bNUlgn
6uNKr69UXetjCoGnpsaut8D1spZC5LSaHJ0d1czXz8RDc7d5Xl9JkXeLGk6noLyv069jXdNk
vHUxiHZKk/clm/mSVvMxB7N+Wwrb+ur8Rl5vV7WKquUlh2kYw5Hzcn1uJ5KV344XmvjGZUpE
Stoq+wVtm/1QsoBjNO341mdqLcsKuza3xemjv4aNbm0aIxcZr6vahaTTlXfDKXC0/hPnbbIh
dLuFtK3JJRedK9LWwkv4dazpvPpsU+lmWzg6OQPk79IYL24UG9bslrl36/rubP6q+62s5Pf9
wHc1PnlNpg9l0CfL+PFzjx2XGxkfGnh7uNz5iO/djLTU957HpfBBL+pD0eqTRd9D7o/6e7y+
FvihAf0zWF0OlqCfvepL4Vohc/xLuiQb8JEHU5ZKK8zje+XvT6sPycePmnz4Ht4L/c7BjvxQ
okqyG1PpV7RJyfVaJ3XoNLfogiEllSAVaYLorhsnctwrZOQlenur3985r7+vxDrOVa7h5t79
g2aV7QOJ5jA3Zp3MfkE78spr5nXxXL0erGVDloocPvFtUd4Zmr3e9SJbgfZzf8nBurVNy3Qo
ye30uaENTd1KTi2JhPxyNutjV2NFaXsgTNKB5lK9tJLLyr5x1OeWrIjnTVJcK7mhyCW72Fil
RVKxeefJNrbtTDT4diYsRe0z70dtfGYwi2RAEm5b7UfOj82tm6eHlvLEeapzuaI957ZIJuBl
gM4pTefcynGfv+dXGCXispx2WSvuXdu8BEn6K6f8lk5tdzJYkhnObZP1/Nj3xHPwzGNa+Sog
s/Zr7b7Z3nVVh6qmhiXLeVvlkNdkzlZiYLWrbqpApuj7RLfd5Dy/acdUJWViard6qGJL9HmW
JnV9bG7H1LflgTDpfshB1wvavEn22sPOR5AlmSP9rHDmvp8P8kI+nxX5WC2UIh2V25Hlo+fZ
MrZt2+/VEs/L1vHg3PIeHhmmXbofb0eC/RZaaKGFFlpooYUWWmihhRZaaKGFFlpooYUWWmih
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
--------------4B194FF8F3EA3786FF9EAE1F
Content-Type: application/x-compressed-tar;
 name="brin-stress-test.tgz"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
 filename="brin-stress-test.tgz"

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
4sSJE/vk/y10LU4AkAEA
--------------4B194FF8F3EA3786FF9EAE1F
Content-Type: application/x-compressed-tar;
 name="brin-bench.tgz"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
 filename="brin-bench.tgz"

H4sIAAAAAAAAA+2d33PqxhmGfWv9FVsfpoYWjiUsMIPjzJyLpDedpJM07UVPBwu0gOaApEjC
dtP0f+9KwjY/LGnF0aJd825mYicSQnpY8ejVh/nGgeN2xtSdzK/G8a+OS6OO4z+YH8P5WUVD
Z+PGNJOfht7f+qnrfVO/vjkzTF3vXfe6va5xpht9s989I3pVO5A3VmFkBYSc+V4YzQIaZq1X
tFzR8eEPV2PHvRpb4VzTfvjpx3/+fNcwtL99+st37Jeu9o9Pf/0l/u1a++mXH36+62maHXi+
PSadjjPt0CcnjEIS0TDSJgG1IsqWJP+l+eGvi+RX8i25sunDlbtaLEj32z8a5Jtvvvvx+/X6
ZLpyJ5HjuSSwXNtbjhy/6Y8erAVx3KhFAhqtAjck8awkVkg+Nz43tDGdOa5G2EgXk0uje/NR
Z/8Yl8NhsuqfSbKRW4269q0WP4osLHe2smaU+At/xnbuVov3QvtAlp7rRZ7rTNrsGSbsAY47
ayfPuHkUnQm5WO/yyl14sxm1SWSNF5REpGklq7cu9o51ZwOOG9Igig/NYw8L6YJOoo0Dd1pk
GnhLMqMuDdgzjdjaDg2bRruRvDItErJ1Cp/lwZqsVktiudbiP7+x/St8wGROJ198j+3WG6tq
4d19snqHrfzp9UHrvfdno8iLrMUooAsrfiFHofMbbV5Gl62Le02begEJ2AGT+5D+SgzSiKfR
/S2xPU07/8BewNlqwU6/cRRQylaz6ZN2vjl14vekj9HSX0+az5GzZC/P8+RJHkAc+4mwCRS/
Dq3bZH6+Lli/yufR3T07eX3yd2dJXzf6O5lTyyYdl+3Z78R6/EIu/+uzhRFpdP93yXb/nE7m
3usM6bAJQl7eIdd7nb42pJGcM6SRnjGkEZJGQBpRcpjxExK240vr6asPchWyZekW2fGSRyea
k6bPJnY48mkwYrOJzfG79e4cmUcskPVhclNZLSJHCJtkx0bplkfJ04w8P2yyt4XVLqt071oy
0oz3uyzT8cJj7yICYCYbjilKSCo96CJEtufS3bf1ZE/X7+VvvQHmOqJNfMu2qV3SFW0Si/Kp
Cme0ydLuNZ3hMNkeDKKQQTrp3IFIMrDAJ6KgQivlgB3LLjaVM4KkR9422h0DDqnbIfEkQQzJ
AQJvVI8TxuBFVZcr1IgiMIm0JkEcKeACrwijCr2UJCbOMh8qGju6MnSd2E4YOS57m01naT0Z
Z+nZTafNdqeFu2WS+4m9SKi5FDOBl4QQhZNK0DpW6ok18mwPyWoxG2JBUUZpzSAJFaOBdESC
hXvKQzumgvaSTN2Vm8JUgxtvkhkHZRwOKLCMGKTwSxlcUplFjphDuHMOxCO1eJB1ONhAQ0LJ
wkYHUFOxAiRdDQhVICWchToQHxV4ShBTGKoUryMGJgXqQagIvQPlICfxwIGAxKKFhw7Bdlwd
yVsbQnVIIfugPsSFBcYRBRWuKQdMMsvIEX9IifwDCUkuIWQgLjpQkmC2MNNB3NSoGKUGkegP
hprxnvxp/T+arVb8JXO4hSenv9IXKT4VEJ0yYMBO1aKEjHgwCQ1Hm8rYNEXdEehtc6AUpKZH
Tj395DKBVYQQhVxK0FIu38iUcJBx1HMTUk4ODhipapiQER+oY2UdCdMO8s57cgoSTy4VGEYQ
U4imFC9xvqm7PRGG4JHOn/3+X/0j9v8y9I3+X+ZN0v/rBv2/jjKk7f81dmalWoCxmTQ0p4Ph
9XBsDbtUHw6M6XQ4pd3u0DamxpXRHex0B2MXqkY6BdEnDNfQwhpJ9E/26jmTB66bK6eJK2ZO
UugThrswqhnk1G/DFGGBT0RBhVbKAUOfMPwFhzQO2fokOGLIPhB4o3qcMAYvKvQJw98CKmkS
xJECLvCKMKrQS0lianwmFn3C4KevmP+7fSEQdt5kAi8JIQonlaCFPmHoE/ZuNIMkVIwG0hEJ
Fu4pD02qbi7SpRrceJPMOCjjcECBZcQghV/K4JLKLHLEHPQJeyfiQdbhYAMNCSULGx1ATcUK
kHQ1IFSBlHAW6kB8VOApQUxhqFK80CcMfcLemXKQk3jgQEBi0cJDh2CTrIOLhGkHN+mksw/q
Q1xYYBxRUOGacsAks4wc8Qd9wt6RhJCBuOhASYLZwkwHcVOjYoQ+YfBXlb0kTjc6vQ0DdqoW
JWTEgwl9wvC9+Yp75NTTTy4TWEUIUcilBC3l8o1MCQcZRz03IeXk4ICRqoYJGfGBQp8w5J13
4RQknlwqMIwgphBNKV7oE4axM9J5sdn/KzIrbP2VjIL+X93e9fVL/y+zZ5zpRq/XRf+vowxR
/b+ye6FEZqnrzkMvNx1cP8p4/bjbRCE63b7lb6GQ7UoxMhW4UswEKc/lIeMozcd/tiHV0g8r
Mg+6B/G1tyAc3GFQ0RCnfnchhwh8IYAntMHNqp4eJvVGCPz1gUSOWH+KGTFimwW8UClJGIGD
Ul0ukDdKwBQymgJxIhsJvCECKPTBD0uNz2YW96s6UkZ5/Tp33M2S2z+vPQkQVvZwwDtVw4Rz
+EDV3o+qpgDzKg4URVTVCJJMLhVIRRBTuKUUL4m6gkiSSnBjTDKjoIySyQMWqZwm/MFJSipz
1BhTCG9OgVhkFQuySj4WaEYUVNimHDAVKzBy1GBQhVHBSajD5AGBh6rHCQPxopKgH1Td9RhU
ZJRWCnJOARcIRhhVeKYkMak6cUiTVnATTTq7oD6TQwRGEcATLuFmJZlFaq7ToFKjvGSQYYrA
QDnisMI8ZZGpUbEp6Nd0pPiz3WkD99ZkFNPWF/ifcObZ4wDtVEYRlikgVEMjppqyy7YSUHxR
ThCnnleycEAXVcOENfhAKZdI6s4kSCUKSQe5ZI8EVFMhR1imkFEtrZPqyydIKKrLAhklCwjU
UT1OGIQX1Yn3REoZbPX/GRy7/0/f2Oj/c6On/X/66P9zjFFD/59BiYunsTM7PFajBZCUl0Z7
Xyk/ONmLordQSHc5NFDgcigTpEQXQoO6L4SyINXTAmhwQJZOdYAuQKcoiVMP0DlEoAwBPGEO
blY1dX6oO0jgI+wSaeL5k7EIE1ssoIZKSUIKHJTq0oHUgQKykFEWCBXZSKAOEUBhEH5YanyK
kKMX0NGSCtoBqaKgjW+LR2TZxQH1VA0T2uEDVX87oNpiDDoCqW8S5JlcKvCKIKbQSyleMvV1
kCab4A6ZZFJBSSWTB0RSOU0ohJOUVPKoN6ygL5DybkFiyccC04iCCuGUA6ZiNUaaegwqMipo
CTWZPCBQUfU4ISFeVDK0Bqq/NoPqjNJWQdop4ALHCKMK1ZQkJldfB4kyC+6mSScY1GpyiEAq
AnhCJ9ysJBNJ/TUbVG2U9wySTBEYWEccVsinLDI1qjdFPYKOFoLQJkh+N21/Af3pJp89DjBP
ZRQhmgJCdbQJqi3BoFOQ4o449dSShQPGqBomxMEHSrlcIkEyQTZRyDtIJ3skYJsKOUI0hYzq
aRZUZ0pBTlHdF0gqWUBgj+pxQiK8qN5Zv6D0mF76/1Td+icZ+f1/2DLdfOn/cxP/f8Psmwb6
/xxjbPX/yejtsz9Xt5r9vDGVHzN8PvceSfxG6VuBtVjQxWhpsROMupY7oaNHL/hCgzBWujMl
/yIXjccLdrJScqFfkH/fkmhO3fUpesESeHIiPW+IbGyIPG+IrfzksMshbepsXCUk57W+/qGv
LxPipX6ytE/6JjG6g/WCZMlDvGRArrubC84/vnTMMtlpk5z5Pmk8bC8abC3aWkajjuM/ZD82
Xd7f3UD61rL+kfy77jmEgYGBgYGBgYGBgaHG+D9xSRWUALgBAA==
--------------4B194FF8F3EA3786FF9EAE1F--





^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/9] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 4e0c9be58c..4099e72001 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8191,7 +8191,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------0E72B707603BED22B4040825--





^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/9] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 1487710d59..33841e14f2 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8191,7 +8191,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------22A4B241170149838D4D1F8F
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210215.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210215.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 58fe109d2d..8a1a9da78f 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -389,6 +389,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -410,6 +413,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -470,7 +528,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -480,51 +538,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index d7b55f57ea..871e024e00 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8143,7 +8143,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8159,7 +8159,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------CF71AF65F7C337C37C24B045
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210112.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210112.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/6] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 58fe109d2d..8a1a9da78f 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -389,6 +389,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -410,6 +413,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -470,7 +528,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -480,51 +538,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index d7b55f57ea..871e024e00 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8143,7 +8143,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8159,7 +8159,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------D21F32E0F9E7408E9BE1AF2E
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210114.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210114.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/6] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index d27336adcd..f3ead7d53d 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8145,7 +8145,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8161,7 +8161,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------310A2AE1CC4C2E2E77559E3D
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-suppo-20210114-2.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-suppo-20210114-2.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index b5f52d4e4a..2ef11245a8 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8183,7 +8183,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8199,7 +8199,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------FA974B75A0C3E9CA18CE7207
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210122.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210122.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/6] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 158 ++++++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 140 ++++++++++++++------
 src/backend/access/brin/brin_minmax.c    |  92 ++++++++++---
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 303 insertions(+), 95 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..963b7079cf 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,78 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of
+					 * multiple scan keys. We can determine that based on the
+					 * number of arguments - functions with extra parameter
+					 * (number of scan keys) do support this, otherwise we
+					 * have to simply pass the scan keys one by one, as
+					 * before.
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same
+						 * for all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet
+						 * the criteria for a single one of them is enough to
+						 * discard the range as a whole, so break out of the
+						 * loop as soon as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+
+							/* mismatching key, no need to look further  */
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..a260074c91 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -251,6 +253,10 @@ brin_inclusion_add_value(PG_FUNCTION_ARGS)
 /*
  * BRIN inclusion consistent function
  *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
+ *
  * All of the strategies are optional.
  */
 Datum
@@ -258,24 +264,31 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/* Handle IS NULL/IS NOT NULL tests */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -284,7 +297,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -293,7 +311,14 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
@@ -301,10 +326,45 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all regular scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* Skip IS NULL/IS NOT NULL keys (already handled above). */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
+	/* This should be called only for regular keys, not for IS [NOT] NULL. */
+	Assert(!(key->sk_flags & SK_ISNULL));
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +384,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +444,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +464,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +483,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +518,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +528,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..e116084a02 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -140,29 +142,41 @@ brin_minmax_add_value(PG_FUNCTION_ARGS)
  * Given an index tuple corresponding to a certain page range and a scan key,
  * return whether the scan key is consistent with the index tuple's min/max
  * values.  Return true if so, false otherwise.
+ *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
  */
 Datum
 brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
 	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -171,7 +185,12 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -180,13 +199,52 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
+	}
+
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
+
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +287,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 1487710d59..33841e14f2 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8191,7 +8191,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------6A37408A2C42B5B56C3B3D49
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210303.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210303.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c          | 158 +++++++++++++++++++-----
 src/backend/access/brin/brin_validate.c |   4 +-
 2 files changed, 126 insertions(+), 36 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..963b7079cf 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,78 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of
+					 * multiple scan keys. We can determine that based on the
+					 * number of arguments - functions with extra parameter
+					 * (number of scan keys) do support this, otherwise we
+					 * have to simply pass the scan keys one by one, as
+					 * before.
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same
+						 * for all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet
+						 * the criteria for a single one of them is enough to
+						 * discard the range as a whole, so break out of the
+						 * loop as soon as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+
+							/* mismatching key, no need to look further  */
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-- 
2.26.2


--------------AC3FFB734F56C5F52D422EFC
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Process-all-scan-keys-in-existing-BRIN-opcl-20210305.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Process-all-scan-keys-in-existing-BRIN-opcl-20210305.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c          | 158 +++++++++++++++++++-----
 src/backend/access/brin/brin_validate.c |   4 +-
 2 files changed, 126 insertions(+), 36 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..f9a0476024 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,78 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any scan keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of
+					 * multiple scan keys. We can determine that based on the
+					 * number of arguments - functions with extra parameter
+					 * (number of scan keys) do support this, otherwise we
+					 * have to simply pass the scan keys one by one, as
+					 * before.
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same
+						 * for all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet
+						 * the criteria for a single one of them is enough to
+						 * discard the range as a whole, so break out of the
+						 * loop as soon as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+
+							/* mismatching key, no need to look further  */
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-- 
2.26.2


--------------82D677E9F94AC7574E460205
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Process-all-scan-keys-in-existing-BRIN-opcl-20210308.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Process-all-scan-keys-in-existing-BRIN-opcl-20210308.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c          | 158 +++++++++++++++++++-----
 src/backend/access/brin/brin_validate.c |   4 +-
 2 files changed, 126 insertions(+), 36 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..f9a0476024 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,78 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any scan keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of
+					 * multiple scan keys. We can determine that based on the
+					 * number of arguments - functions with extra parameter
+					 * (number of scan keys) do support this, otherwise we
+					 * have to simply pass the scan keys one by one, as
+					 * before.
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same
+						 * for all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet
+						 * the criteria for a single one of them is enough to
+						 * discard the range as a whole, so break out of the
+						 * loop as soon as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+
+							/* mismatching key, no need to look further  */
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-- 
2.26.2


--------------556A1DC61262AF15641DB204
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Process-all-scan-keys-in-existing-BRIN-opc-20210308b.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Process-all-scan-keys-in-existing-BRIN-opc-20210308b.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow future opclases to benefit from seeing all keys at once.

This does break existing BRIN opclasses, because the signature of the
consistent function changed. We might support both variants (with 3 and
4 parameters), but that seems pointless - the changes to NULL handling
likely require updates too. So better to make the failure clear. Also,
we're not aware of any out-of-core opclasses - there may be some, but
probably not many.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 doc/src/sgml/brin.sgml                   |   8 +-
 src/backend/access/brin/brin.c           | 118 +++++++++++++------
 src/backend/access/brin/brin_inclusion.c | 140 ++++++++++++++++-------
 src/backend/access/brin/brin_minmax.c    |  92 ++++++++++++---
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 6 files changed, 269 insertions(+), 97 deletions(-)

diff --git a/doc/src/sgml/brin.sgml b/doc/src/sgml/brin.sgml
index 06880c0f7b..078f51bb55 100644
--- a/doc/src/sgml/brin.sgml
+++ b/doc/src/sgml/brin.sgml
@@ -464,12 +464,14 @@ typedef struct BrinOpcInfo
 
    <varlistentry>
     <term><function>bool consistent(BrinDesc *bdesc, BrinValues *column,
-       ScanKey key)</function></term>
+       ScanKey *keys, int nkeys)</function></term>
     <listitem>
      <para>
-      Returns whether the ScanKey is consistent with the given indexed
-      values for a range.
+      Returns whether all the ScanKey entries are consistent with the given
+      indexed values for a range.
       The attribute number to use is passed as part of the scan key.
+      Multiple scan keys for the same attribute may be passed at once, the
+      number of entries is determined by the <literal>nkeys</literal> parameter.
      </para>
     </listitem>
    </varlistentry>
diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..743f2a925a 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,40 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
+					Oid			collation;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
-
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
-
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					/* skip attributes without any scan keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
+
+					bval = &dtup->bt_columns[attno - 1];
+
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * XXX We simply use the collation from the first key (it
+					 * has to be the same for all keys for the same attribue).
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
+					collation = keys[attno - 1][0]->sk_collation;
+
+					/* Check all keys at once */
+					add = FunctionCall4Coll(&consistentFn[attno - 1],
+											collation,
 											PointerGetDatum(bdesc),
 											PointerGetDatum(bval),
-											PointerGetDatum(key));
+											PointerGetDatum(keys[attno - 1]),
+											Int32GetDatum(nkeys[attno - 1]));
 					addrange = DatumGetBool(add);
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..a260074c91 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -251,6 +253,10 @@ brin_inclusion_add_value(PG_FUNCTION_ARGS)
 /*
  * BRIN inclusion consistent function
  *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
+ *
  * All of the strategies are optional.
  */
 Datum
@@ -258,24 +264,31 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/* Handle IS NULL/IS NOT NULL tests */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -284,7 +297,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -293,7 +311,14 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
@@ -301,10 +326,45 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all regular scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* Skip IS NULL/IS NOT NULL keys (already handled above). */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
+	/* This should be called only for regular keys, not for IS [NOT] NULL. */
+	Assert(!(key->sk_flags & SK_ISNULL));
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +384,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +444,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +464,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +483,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +518,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +528,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..e116084a02 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -140,29 +142,41 @@ brin_minmax_add_value(PG_FUNCTION_ARGS)
  * Given an index tuple corresponding to a certain page range and a scan key,
  * return whether the scan key is consistent with the index tuple's min/max
  * values.  Return true if so, false otherwise.
+ *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
  */
 Datum
 brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
 	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -171,7 +185,12 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -180,13 +199,52 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
+	}
+
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
+
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +287,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..2c4f9a3eff 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											4, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index c7619f8cd3..cd1eda38ab 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8223,7 +8223,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------D524CD37E77B36A2883A7617
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Move-IS-NOT-NULL-handling-from-BRIN-support-20210311.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Move-IS-NOT-NULL-handling-from-BRIN-support-20210311.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/9] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 4e0c9be58c..4099e72001 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8191,7 +8191,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------4B194FF8F3EA3786FF9EAE1F
Content-Type: application/vnd.oasis.opendocument.spreadsheet;
 name="brin-bench.ods"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
 filename="brin-bench.ods"

UEsDBBQAAAgAAOO7Q1KFbDmKLgAAAC4AAAAIAAAAbWltZXR5cGVhcHBsaWNhdGlvbi92bmQu
b2FzaXMub3BlbmRvY3VtZW50LnNwcmVhZHNoZWV0UEsDBBQAAAgAAOO7Q1IAAAAAAAAAAAAA
AAAcAAAAQ29uZmlndXJhdGlvbnMyL2FjY2VsZXJhdG9yL1BLAwQUAAAIAADju0NSAAAAAAAA
AAAAAAAAHwAAAENvbmZpZ3VyYXRpb25zMi9pbWFnZXMvQml0bWFwcy9QSwMEFAAACAAA47tD
UgAAAAAAAAAAAAAAABgAAABDb25maWd1cmF0aW9uczIvdG9vbGJhci9QSwMEFAAACAAA47tD
UgAAAAAAAAAAAAAAABgAAABDb25maWd1cmF0aW9uczIvZmxvYXRlci9QSwMEFAAACAAA47tD
UgAAAAAAAAAAAAAAABoAAABDb25maWd1cmF0aW9uczIvcG9wdXBtZW51L1BLAwQUAAAIAADj
u0NSAAAAAAAAAAAAAAAAGAAAAENvbmZpZ3VyYXRpb25zMi9tZW51YmFyL1BLAwQUAAAIAADj
u0NSAAAAAAAAAAAAAAAAGgAAAENvbmZpZ3VyYXRpb25zMi90b29scGFuZWwvUEsDBBQAAAgA
AOO7Q1IAAAAAAAAAAAAAAAAaAAAAQ29uZmlndXJhdGlvbnMyL3N0YXR1c2Jhci9QSwMEFAAA
CAAA47tDUgAAAAAAAAAAAAAAABwAAABDb25maWd1cmF0aW9uczIvcHJvZ3Jlc3NiYXIvUEsD
BBQACAgIAOO7Q1IAAAAAAAAAAAAAAAAMAAAAbWFuaWZlc3QucmRmzZPNboMwEITvPIVlzthA
LwUFcijKuWqfwDWGWAUv8poS3r6Ok1ZRpKrqn9TjrkYz3460m+1hHMiLsqjBVDRjKSXKSGi1
6Ss6uy65pds62ti2Kx+aHfFqg6WfKrp3bio5X5aFLTcMbM+zoih4mvM8T7wiwdU4cUgMxrSO
CAkejUJp9eR8GjnO4glmV1F066CQefcgPYvdOqmgsgphtlK9h7YgkYFAjQlMyoR0gxy6TkvF
M5bzUTnBoe3ix2C904OiPGDwK47P2N6IDKblXuC9sO5cg998lWh67mN6ddPF8d8jlGCcMu5P
6rs7ef/n/i7P/xnir7R2RGxAzqNn+pDntPIfVUevUEsHCLT3aNIFAQAAgwMAAFBLAwQUAAgI
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
qj3ilyQOPhr0ABLtL3rhZyov0EILLbTQQgsttND+W1rqv9n/cfyPtLu9/1v//Op6vYEY/1mt
W6p3rm9s+rFGaz8x2MF6O6wN/SU0Y2o3tvDifH1Jv4qU7vqardljWAZb3pyj1Tq6spysn/fd
2kTWub1a2+VJvKrVtXjeoiYdYprGsV9fxoqz3RtNUinHrl0haYvWpK6ELiWP4mOcD1bNUlgn
6uNKr69UXetjCoGnpsaut8D1spZC5LSaHJ0d1czXz8RDc7d5Xl9JkXeLGk6noLyv069jXdNk
vHUxiHZKk/clm/mSVvMxB7N+Wwrb+ur8Rl5vV7WKquUlh2kYw5Hzcn1uJ5KV344XmvjGZUpE
Stoq+wVtm/1QsoBjNO341mdqLcsKuza3xemjv4aNbm0aIxcZr6vahaTTlXfDKXC0/hPnbbIh
dLuFtK3JJRedK9LWwkv4dazpvPpsU+lmWzg6OQPk79IYL24UG9bslrl36/rubP6q+62s5Pf9
wHc1PnlNpg9l0CfL+PFzjx2XGxkfGnh7uNz5iO/djLTU957HpfBBL+pD0eqTRd9D7o/6e7y+
FvihAf0zWF0OlqCfvepL4Vohc/xLuiQb8JEHU5ZKK8zje+XvT6sPycePmnz4Ht4L/c7BjvxQ
okqyG1PpV7RJyfVaJ3XoNLfogiEllSAVaYLorhsnctwrZOQlenur3985r7+vxDrOVa7h5t79
g2aV7QOJ5jA3Zp3MfkE78spr5nXxXL0erGVDloocPvFtUd4Zmr3e9SJbgfZzf8nBurVNy3Qo
ye30uaENTd1KTi2JhPxyNutjV2NFaXsgTNKB5lK9tJLLyr5x1OeWrIjnTVJcK7mhyCW72Fil
RVKxeefJNrbtTDT4diYsRe0z70dtfGYwi2RAEm5b7UfOj82tm6eHlvLEeapzuaI957ZIJuBl
gM4pTefcynGfv+dXGCXispx2WSvuXdu8BEn6K6f8lk5tdzJYkhnObZP1/Nj3xHPwzGNa+Sog
s/Zr7b7Z3nVVh6qmhiXLeVvlkNdkzlZiYLWrbqpApuj7RLfd5Dy/acdUJWViard6qGJL9HmW
JnV9bG7H1LflgTDpfshB1wvavEn22sPOR5AlmSP9rHDmvp8P8kI+nxX5WC2UIh2V25Hlo+fZ
MrZt2+/VEs/L1vHg3PIeHhmmXbofb0eC/RZaaKGFFlpooYUWWmihhRZaaKGFFlpooYUWWmih
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
--------------4B194FF8F3EA3786FF9EAE1F
Content-Type: application/x-compressed-tar;
 name="brin-stress-test.tgz"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
 filename="brin-stress-test.tgz"

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
4sSJE/vk/y10LU4AkAEA
--------------4B194FF8F3EA3786FF9EAE1F
Content-Type: application/x-compressed-tar;
 name="brin-bench.tgz"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
 filename="brin-bench.tgz"

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
--------------4B194FF8F3EA3786FF9EAE1F--





^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/9] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 4e0c9be58c..4099e72001 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8191,7 +8191,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------0E72B707603BED22B4040825--





^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/9] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 1487710d59..33841e14f2 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8191,7 +8191,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------22A4B241170149838D4D1F8F
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210215.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210215.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 58fe109d2d..8a1a9da78f 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -389,6 +389,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -410,6 +413,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -470,7 +528,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -480,51 +538,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index d7b55f57ea..871e024e00 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8143,7 +8143,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8159,7 +8159,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------CF71AF65F7C337C37C24B045
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210112.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210112.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/6] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 58fe109d2d..8a1a9da78f 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -389,6 +389,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -410,6 +413,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -470,7 +528,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -480,51 +538,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index d7b55f57ea..871e024e00 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8143,7 +8143,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8159,7 +8159,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------D21F32E0F9E7408E9BE1AF2E
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210114.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210114.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/6] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index d27336adcd..f3ead7d53d 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8145,7 +8145,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8161,7 +8161,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------310A2AE1CC4C2E2E77559E3D
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-suppo-20210114-2.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-suppo-20210114-2.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index b5f52d4e4a..2ef11245a8 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8183,7 +8183,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8199,7 +8199,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------FA974B75A0C3E9CA18CE7207
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210122.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210122.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/6] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 158 ++++++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 140 ++++++++++++++------
 src/backend/access/brin/brin_minmax.c    |  92 ++++++++++---
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 303 insertions(+), 95 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..963b7079cf 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,78 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of
+					 * multiple scan keys. We can determine that based on the
+					 * number of arguments - functions with extra parameter
+					 * (number of scan keys) do support this, otherwise we
+					 * have to simply pass the scan keys one by one, as
+					 * before.
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same
+						 * for all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet
+						 * the criteria for a single one of them is enough to
+						 * discard the range as a whole, so break out of the
+						 * loop as soon as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+
+							/* mismatching key, no need to look further  */
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..a260074c91 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -251,6 +253,10 @@ brin_inclusion_add_value(PG_FUNCTION_ARGS)
 /*
  * BRIN inclusion consistent function
  *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
+ *
  * All of the strategies are optional.
  */
 Datum
@@ -258,24 +264,31 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/* Handle IS NULL/IS NOT NULL tests */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -284,7 +297,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -293,7 +311,14 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
@@ -301,10 +326,45 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all regular scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* Skip IS NULL/IS NOT NULL keys (already handled above). */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
+	/* This should be called only for regular keys, not for IS [NOT] NULL. */
+	Assert(!(key->sk_flags & SK_ISNULL));
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +384,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +444,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +464,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +483,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +518,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +528,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..e116084a02 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -140,29 +142,41 @@ brin_minmax_add_value(PG_FUNCTION_ARGS)
  * Given an index tuple corresponding to a certain page range and a scan key,
  * return whether the scan key is consistent with the index tuple's min/max
  * values.  Return true if so, false otherwise.
+ *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
  */
 Datum
 brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
 	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -171,7 +185,12 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -180,13 +199,52 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
+	}
+
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
+
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +287,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 1487710d59..33841e14f2 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8191,7 +8191,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------6A37408A2C42B5B56C3B3D49
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210303.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210303.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c          | 158 +++++++++++++++++++-----
 src/backend/access/brin/brin_validate.c |   4 +-
 2 files changed, 126 insertions(+), 36 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..963b7079cf 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,78 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of
+					 * multiple scan keys. We can determine that based on the
+					 * number of arguments - functions with extra parameter
+					 * (number of scan keys) do support this, otherwise we
+					 * have to simply pass the scan keys one by one, as
+					 * before.
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same
+						 * for all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet
+						 * the criteria for a single one of them is enough to
+						 * discard the range as a whole, so break out of the
+						 * loop as soon as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+
+							/* mismatching key, no need to look further  */
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-- 
2.26.2


--------------AC3FFB734F56C5F52D422EFC
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Process-all-scan-keys-in-existing-BRIN-opcl-20210305.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Process-all-scan-keys-in-existing-BRIN-opcl-20210305.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c          | 158 +++++++++++++++++++-----
 src/backend/access/brin/brin_validate.c |   4 +-
 2 files changed, 126 insertions(+), 36 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..f9a0476024 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,78 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any scan keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of
+					 * multiple scan keys. We can determine that based on the
+					 * number of arguments - functions with extra parameter
+					 * (number of scan keys) do support this, otherwise we
+					 * have to simply pass the scan keys one by one, as
+					 * before.
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same
+						 * for all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet
+						 * the criteria for a single one of them is enough to
+						 * discard the range as a whole, so break out of the
+						 * loop as soon as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+
+							/* mismatching key, no need to look further  */
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-- 
2.26.2


--------------82D677E9F94AC7574E460205
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Process-all-scan-keys-in-existing-BRIN-opcl-20210308.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Process-all-scan-keys-in-existing-BRIN-opcl-20210308.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c          | 158 +++++++++++++++++++-----
 src/backend/access/brin/brin_validate.c |   4 +-
 2 files changed, 126 insertions(+), 36 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..f9a0476024 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,78 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any scan keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of
+					 * multiple scan keys. We can determine that based on the
+					 * number of arguments - functions with extra parameter
+					 * (number of scan keys) do support this, otherwise we
+					 * have to simply pass the scan keys one by one, as
+					 * before.
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same
+						 * for all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet
+						 * the criteria for a single one of them is enough to
+						 * discard the range as a whole, so break out of the
+						 * loop as soon as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+
+							/* mismatching key, no need to look further  */
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-- 
2.26.2


--------------556A1DC61262AF15641DB204
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Process-all-scan-keys-in-existing-BRIN-opc-20210308b.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Process-all-scan-keys-in-existing-BRIN-opc-20210308b.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow future opclases to benefit from seeing all keys at once.

This does break existing BRIN opclasses, because the signature of the
consistent function changed. We might support both variants (with 3 and
4 parameters), but that seems pointless - the changes to NULL handling
likely require updates too. So better to make the failure clear. Also,
we're not aware of any out-of-core opclasses - there may be some, but
probably not many.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 doc/src/sgml/brin.sgml                   |   8 +-
 src/backend/access/brin/brin.c           | 118 +++++++++++++------
 src/backend/access/brin/brin_inclusion.c | 140 ++++++++++++++++-------
 src/backend/access/brin/brin_minmax.c    |  92 ++++++++++++---
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 6 files changed, 269 insertions(+), 97 deletions(-)

diff --git a/doc/src/sgml/brin.sgml b/doc/src/sgml/brin.sgml
index 06880c0f7b..078f51bb55 100644
--- a/doc/src/sgml/brin.sgml
+++ b/doc/src/sgml/brin.sgml
@@ -464,12 +464,14 @@ typedef struct BrinOpcInfo
 
    <varlistentry>
     <term><function>bool consistent(BrinDesc *bdesc, BrinValues *column,
-       ScanKey key)</function></term>
+       ScanKey *keys, int nkeys)</function></term>
     <listitem>
      <para>
-      Returns whether the ScanKey is consistent with the given indexed
-      values for a range.
+      Returns whether all the ScanKey entries are consistent with the given
+      indexed values for a range.
       The attribute number to use is passed as part of the scan key.
+      Multiple scan keys for the same attribute may be passed at once, the
+      number of entries is determined by the <literal>nkeys</literal> parameter.
      </para>
     </listitem>
    </varlistentry>
diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..743f2a925a 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,40 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
+					Oid			collation;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
-
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
-
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					/* skip attributes without any scan keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
+
+					bval = &dtup->bt_columns[attno - 1];
+
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * XXX We simply use the collation from the first key (it
+					 * has to be the same for all keys for the same attribue).
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
+					collation = keys[attno - 1][0]->sk_collation;
+
+					/* Check all keys at once */
+					add = FunctionCall4Coll(&consistentFn[attno - 1],
+											collation,
 											PointerGetDatum(bdesc),
 											PointerGetDatum(bval),
-											PointerGetDatum(key));
+											PointerGetDatum(keys[attno - 1]),
+											Int32GetDatum(nkeys[attno - 1]));
 					addrange = DatumGetBool(add);
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..a260074c91 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -251,6 +253,10 @@ brin_inclusion_add_value(PG_FUNCTION_ARGS)
 /*
  * BRIN inclusion consistent function
  *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
+ *
  * All of the strategies are optional.
  */
 Datum
@@ -258,24 +264,31 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/* Handle IS NULL/IS NOT NULL tests */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -284,7 +297,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -293,7 +311,14 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
@@ -301,10 +326,45 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all regular scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* Skip IS NULL/IS NOT NULL keys (already handled above). */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
+	/* This should be called only for regular keys, not for IS [NOT] NULL. */
+	Assert(!(key->sk_flags & SK_ISNULL));
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +384,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +444,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +464,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +483,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +518,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +528,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..e116084a02 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -140,29 +142,41 @@ brin_minmax_add_value(PG_FUNCTION_ARGS)
  * Given an index tuple corresponding to a certain page range and a scan key,
  * return whether the scan key is consistent with the index tuple's min/max
  * values.  Return true if so, false otherwise.
+ *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
  */
 Datum
 brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
 	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -171,7 +185,12 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -180,13 +199,52 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
+	}
+
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
+
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +287,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..2c4f9a3eff 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											4, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index c7619f8cd3..cd1eda38ab 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8223,7 +8223,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------D524CD37E77B36A2883A7617
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Move-IS-NOT-NULL-handling-from-BRIN-support-20210311.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Move-IS-NOT-NULL-handling-from-BRIN-support-20210311.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/9] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 4e0c9be58c..4099e72001 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8191,7 +8191,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------4B194FF8F3EA3786FF9EAE1F
Content-Type: application/vnd.oasis.opendocument.spreadsheet;
 name="brin-bench.ods"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
 filename="brin-bench.ods"

UEsDBBQAAAgAAOO7Q1KFbDmKLgAAAC4AAAAIAAAAbWltZXR5cGVhcHBsaWNhdGlvbi92bmQu
b2FzaXMub3BlbmRvY3VtZW50LnNwcmVhZHNoZWV0UEsDBBQAAAgAAOO7Q1IAAAAAAAAAAAAA
AAAcAAAAQ29uZmlndXJhdGlvbnMyL2FjY2VsZXJhdG9yL1BLAwQUAAAIAADju0NSAAAAAAAA
AAAAAAAAHwAAAENvbmZpZ3VyYXRpb25zMi9pbWFnZXMvQml0bWFwcy9QSwMEFAAACAAA47tD
UgAAAAAAAAAAAAAAABgAAABDb25maWd1cmF0aW9uczIvdG9vbGJhci9QSwMEFAAACAAA47tD
UgAAAAAAAAAAAAAAABgAAABDb25maWd1cmF0aW9uczIvZmxvYXRlci9QSwMEFAAACAAA47tD
UgAAAAAAAAAAAAAAABoAAABDb25maWd1cmF0aW9uczIvcG9wdXBtZW51L1BLAwQUAAAIAADj
u0NSAAAAAAAAAAAAAAAAGAAAAENvbmZpZ3VyYXRpb25zMi9tZW51YmFyL1BLAwQUAAAIAADj
u0NSAAAAAAAAAAAAAAAAGgAAAENvbmZpZ3VyYXRpb25zMi90b29scGFuZWwvUEsDBBQAAAgA
AOO7Q1IAAAAAAAAAAAAAAAAaAAAAQ29uZmlndXJhdGlvbnMyL3N0YXR1c2Jhci9QSwMEFAAA
CAAA47tDUgAAAAAAAAAAAAAAABwAAABDb25maWd1cmF0aW9uczIvcHJvZ3Jlc3NiYXIvUEsD
BBQACAgIAOO7Q1IAAAAAAAAAAAAAAAAMAAAAbWFuaWZlc3QucmRmzZPNboMwEITvPIVlzthA
LwUFcijKuWqfwDWGWAUv8poS3r6Ok1ZRpKrqn9TjrkYz3460m+1hHMiLsqjBVDRjKSXKSGi1
6Ss6uy65pds62ti2Kx+aHfFqg6WfKrp3bio5X5aFLTcMbM+zoih4mvM8T7wiwdU4cUgMxrSO
CAkejUJp9eR8GjnO4glmV1F066CQefcgPYvdOqmgsgphtlK9h7YgkYFAjQlMyoR0gxy6TkvF
M5bzUTnBoe3ix2C904OiPGDwK47P2N6IDKblXuC9sO5cg998lWh67mN6ddPF8d8jlGCcMu5P
6rs7ef/n/i7P/xnir7R2RGxAzqNn+pDntPIfVUevUEsHCLT3aNIFAQAAgwMAAFBLAwQUAAgI
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
qj3ilyQOPhr0ABLtL3rhZyov0EILLbTQQgsttND+W1rqv9n/cfyPtLu9/1v//Op6vYEY/1mt
W6p3rm9s+rFGaz8x2MF6O6wN/SU0Y2o3tvDifH1Jv4qU7vqardljWAZb3pyj1Tq6spysn/fd
2kTWub1a2+VJvKrVtXjeoiYdYprGsV9fxoqz3RtNUinHrl0haYvWpK6ELiWP4mOcD1bNUlgn
6uNKr69UXetjCoGnpsaut8D1spZC5LSaHJ0d1czXz8RDc7d5Xl9JkXeLGk6noLyv069jXdNk
vHUxiHZKk/clm/mSVvMxB7N+Wwrb+ur8Rl5vV7WKquUlh2kYw5Hzcn1uJ5KV344XmvjGZUpE
Stoq+wVtm/1QsoBjNO341mdqLcsKuza3xemjv4aNbm0aIxcZr6vahaTTlXfDKXC0/hPnbbIh
dLuFtK3JJRedK9LWwkv4dazpvPpsU+lmWzg6OQPk79IYL24UG9bslrl36/rubP6q+62s5Pf9
wHc1PnlNpg9l0CfL+PFzjx2XGxkfGnh7uNz5iO/djLTU957HpfBBL+pD0eqTRd9D7o/6e7y+
FvihAf0zWF0OlqCfvepL4Vohc/xLuiQb8JEHU5ZKK8zje+XvT6sPycePmnz4Ht4L/c7BjvxQ
okqyG1PpV7RJyfVaJ3XoNLfogiEllSAVaYLorhsnctwrZOQlenur3985r7+vxDrOVa7h5t79
g2aV7QOJ5jA3Zp3MfkE78spr5nXxXL0erGVDloocPvFtUd4Zmr3e9SJbgfZzf8nBurVNy3Qo
ye30uaENTd1KTi2JhPxyNutjV2NFaXsgTNKB5lK9tJLLyr5x1OeWrIjnTVJcK7mhyCW72Fil
RVKxeefJNrbtTDT4diYsRe0z70dtfGYwi2RAEm5b7UfOj82tm6eHlvLEeapzuaI957ZIJuBl
gM4pTefcynGfv+dXGCXispx2WSvuXdu8BEn6K6f8lk5tdzJYkhnObZP1/Nj3xHPwzGNa+Sog
s/Zr7b7Z3nVVh6qmhiXLeVvlkNdkzlZiYLWrbqpApuj7RLfd5Dy/acdUJWViard6qGJL9HmW
JnV9bG7H1LflgTDpfshB1wvavEn22sPOR5AlmSP9rHDmvp8P8kI+nxX5WC2UIh2V25Hlo+fZ
MrZt2+/VEs/L1vHg3PIeHhmmXbofb0eC/RZaaKGFFlpooYUWWmihhRZaaKGFFlpooYUWWmih
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
--------------4B194FF8F3EA3786FF9EAE1F
Content-Type: application/x-compressed-tar;
 name="brin-stress-test.tgz"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
 filename="brin-stress-test.tgz"

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
4sSJE/vk/y10LU4AkAEA
--------------4B194FF8F3EA3786FF9EAE1F
Content-Type: application/x-compressed-tar;
 name="brin-bench.tgz"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
 filename="brin-bench.tgz"

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
--------------4B194FF8F3EA3786FF9EAE1F--





^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/9] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 4e0c9be58c..4099e72001 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8191,7 +8191,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------0E72B707603BED22B4040825--





^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/9] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 1487710d59..33841e14f2 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8191,7 +8191,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------22A4B241170149838D4D1F8F
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210215.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210215.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 58fe109d2d..8a1a9da78f 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -389,6 +389,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -410,6 +413,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -470,7 +528,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -480,51 +538,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index d7b55f57ea..871e024e00 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8143,7 +8143,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8159,7 +8159,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------CF71AF65F7C337C37C24B045
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210112.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210112.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/6] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 58fe109d2d..8a1a9da78f 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -389,6 +389,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -410,6 +413,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -470,7 +528,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -480,51 +538,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index d7b55f57ea..871e024e00 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8143,7 +8143,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8159,7 +8159,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------D21F32E0F9E7408E9BE1AF2E
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210114.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210114.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/6] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index d27336adcd..f3ead7d53d 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8145,7 +8145,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8161,7 +8161,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------310A2AE1CC4C2E2E77559E3D
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-suppo-20210114-2.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-suppo-20210114-2.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 150 +++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 170 +++++++++++++++--------
 src/backend/access/brin/brin_minmax.c    | 121 +++++++++++-----
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 324 insertions(+), 125 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..dc187153aa 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey	  **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,61 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation
+		 * used in the index column (but only if the search is not
+		 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
+		 * this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno-1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many
+			 * scan keys are there for this attribute, so we simply
+			 * allocate the largest number possible. This may waste
+			 * a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible,
+			 * and it's cheaper than having to repalloc repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +529,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int		attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +539,75 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of multiple
+					 * scan keys. We can determine that based on the number of
+					 * arguments - functions with extra parameter (number of scan
+					 * keys) do support this, otherwise we have to simply pass the
+					 * scan keys one by one,
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same for
+						 * all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet the
+						 * criteria for a single one of them is enough to discard
+						 * the range as a whole, so break out of the loop as soon
+						 * as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..215bc794d3 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -258,53 +260,109 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
-			PG_RETURN_BOOL(false);
-		}
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+				PG_RETURN_BOOL(false);
+			}
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
-		 */
-		PG_RETURN_BOOL(false);
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
+			PG_RETURN_BOOL(false);
+		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
-	if (column->bv_allnulls)
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
 		PG_RETURN_BOOL(false);
 
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
+
 	/* It has to be checked, if it contains elements that are not mergeable. */
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +382,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +442,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +462,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +481,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
-													RTAdjacentStrategyNumber);
+														RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +516,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +526,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..12878ff3a0 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -146,47 +148,104 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey	   *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		regular_keys = false;
 
-	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	/*
+	 * First check if there are any IS NULL scan keys, and if we're
+	 * violating them. In that case we can terminate early, without
+	 * inspecting the ranges.
+	 */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		if (key->sk_flags & SK_SEARCHNULL)
+		ScanKey	key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* handle IS NULL/IS NOT NULL tests */
+		if (key->sk_flags & SK_ISNULL)
 		{
-			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+			if (key->sk_flags & SK_SEARCHNULL)
+			{
+				if (column->bv_allnulls || column->bv_hasnulls)
+					continue;	/* this key is fine, continue */
+
+				PG_RETURN_BOOL(false);
+			}
+
+			/*
+			 * For IS NOT NULL, we can only skip ranges that are known to have
+			 * only nulls.
+			 */
+			if (key->sk_flags & SK_SEARCHNOTNULL)
+			{
+				if (column->bv_allnulls)
+					PG_RETURN_BOOL(false);
+
+				continue;
+			}
+
+			/*
+			 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
+			 * operators are strict and return false.
+			 */
 			PG_RETURN_BOOL(false);
 		}
+		else
+			/* note we have regular (non-NULL) scan keys */
+			regular_keys = true;
+	}
 
-		/*
-		 * For IS NOT NULL, we can only skip ranges that are known to have
-		 * only nulls.
-		 */
-		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+	/*
+	 * If the page range is all nulls, it cannot possibly be consistent if
+	 * there are some regular scan keys.
+	 */
+	if (column->bv_allnulls && regular_keys)
+		PG_RETURN_BOOL(false);
+
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!regular_keys)
+		PG_RETURN_BOOL(true);
 
-		/*
-		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
-		 * operators are strict and return false.
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey	key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		 /*
+		 * When there are multiple scan keys, failure to meet the
+		 * criteria for a single one of them is enough to discard
+		 * the range as a whole, so break out of the loop as soon
+		 * as a false return value is obtained.
 		 */
-		PG_RETURN_BOOL(false);
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
-	if (column->bv_allnulls)
-		PG_RETURN_BOOL(false);
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +288,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index b5f52d4e4a..2ef11245a8 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8183,7 +8183,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8199,7 +8199,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------FA974B75A0C3E9CA18CE7207
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210122.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210122.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/6] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 158 ++++++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 140 ++++++++++++++------
 src/backend/access/brin/brin_minmax.c    |  92 ++++++++++---
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 303 insertions(+), 95 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..963b7079cf 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,78 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of
+					 * multiple scan keys. We can determine that based on the
+					 * number of arguments - functions with extra parameter
+					 * (number of scan keys) do support this, otherwise we
+					 * have to simply pass the scan keys one by one, as
+					 * before.
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same
+						 * for all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet
+						 * the criteria for a single one of them is enough to
+						 * discard the range as a whole, so break out of the
+						 * loop as soon as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+
+							/* mismatching key, no need to look further  */
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..a260074c91 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -251,6 +253,10 @@ brin_inclusion_add_value(PG_FUNCTION_ARGS)
 /*
  * BRIN inclusion consistent function
  *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
+ *
  * All of the strategies are optional.
  */
 Datum
@@ -258,24 +264,31 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/* Handle IS NULL/IS NOT NULL tests */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -284,7 +297,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -293,7 +311,14 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
@@ -301,10 +326,45 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all regular scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* Skip IS NULL/IS NOT NULL keys (already handled above). */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
+	/* This should be called only for regular keys, not for IS [NOT] NULL. */
+	Assert(!(key->sk_flags & SK_ISNULL));
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +384,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +444,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +464,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +483,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +518,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +528,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..e116084a02 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -140,29 +142,41 @@ brin_minmax_add_value(PG_FUNCTION_ARGS)
  * Given an index tuple corresponding to a certain page range and a scan key,
  * return whether the scan key is consistent with the index tuple's min/max
  * values.  Return true if so, false otherwise.
+ *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
  */
 Datum
 brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
 	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -171,7 +185,12 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -180,13 +199,52 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
+	}
+
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
+
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +287,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 1487710d59..33841e14f2 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8191,7 +8191,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------6A37408A2C42B5B56C3B3D49
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210303.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210303.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c          | 158 +++++++++++++++++++-----
 src/backend/access/brin/brin_validate.c |   4 +-
 2 files changed, 126 insertions(+), 36 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..963b7079cf 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,78 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of
+					 * multiple scan keys. We can determine that based on the
+					 * number of arguments - functions with extra parameter
+					 * (number of scan keys) do support this, otherwise we
+					 * have to simply pass the scan keys one by one, as
+					 * before.
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same
+						 * for all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet
+						 * the criteria for a single one of them is enough to
+						 * discard the range as a whole, so break out of the
+						 * loop as soon as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+
+							/* mismatching key, no need to look further  */
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-- 
2.26.2


--------------AC3FFB734F56C5F52D422EFC
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Process-all-scan-keys-in-existing-BRIN-opcl-20210305.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Process-all-scan-keys-in-existing-BRIN-opcl-20210305.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c          | 158 +++++++++++++++++++-----
 src/backend/access/brin/brin_validate.c |   4 +-
 2 files changed, 126 insertions(+), 36 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..f9a0476024 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,78 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any scan keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of
+					 * multiple scan keys. We can determine that based on the
+					 * number of arguments - functions with extra parameter
+					 * (number of scan keys) do support this, otherwise we
+					 * have to simply pass the scan keys one by one, as
+					 * before.
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same
+						 * for all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet
+						 * the criteria for a single one of them is enough to
+						 * discard the range as a whole, so break out of the
+						 * loop as soon as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+
+							/* mismatching key, no need to look further  */
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-- 
2.26.2


--------------82D677E9F94AC7574E460205
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Process-all-scan-keys-in-existing-BRIN-opcl-20210308.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Process-all-scan-keys-in-existing-BRIN-opcl-20210308.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c          | 158 +++++++++++++++++++-----
 src/backend/access/brin/brin_validate.c |   4 +-
 2 files changed, 126 insertions(+), 36 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..f9a0476024 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,78 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any scan keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of
+					 * multiple scan keys. We can determine that based on the
+					 * number of arguments - functions with extra parameter
+					 * (number of scan keys) do support this, otherwise we
+					 * have to simply pass the scan keys one by one, as
+					 * before.
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same
+						 * for all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet
+						 * the criteria for a single one of them is enough to
+						 * discard the range as a whole, so break out of the
+						 * loop as soon as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+
+							/* mismatching key, no need to look further  */
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-- 
2.26.2


--------------556A1DC61262AF15641DB204
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Process-all-scan-keys-in-existing-BRIN-opc-20210308b.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Process-all-scan-keys-in-existing-BRIN-opc-20210308b.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow future opclases to benefit from seeing all keys at once.

This does break existing BRIN opclasses, because the signature of the
consistent function changed. We might support both variants (with 3 and
4 parameters), but that seems pointless - the changes to NULL handling
likely require updates too. So better to make the failure clear. Also,
we're not aware of any out-of-core opclasses - there may be some, but
probably not many.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 doc/src/sgml/brin.sgml                   |   8 +-
 src/backend/access/brin/brin.c           | 118 +++++++++++++------
 src/backend/access/brin/brin_inclusion.c | 140 ++++++++++++++++-------
 src/backend/access/brin/brin_minmax.c    |  92 ++++++++++++---
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 6 files changed, 269 insertions(+), 97 deletions(-)

diff --git a/doc/src/sgml/brin.sgml b/doc/src/sgml/brin.sgml
index 06880c0f7b..078f51bb55 100644
--- a/doc/src/sgml/brin.sgml
+++ b/doc/src/sgml/brin.sgml
@@ -464,12 +464,14 @@ typedef struct BrinOpcInfo
 
    <varlistentry>
     <term><function>bool consistent(BrinDesc *bdesc, BrinValues *column,
-       ScanKey key)</function></term>
+       ScanKey *keys, int nkeys)</function></term>
     <listitem>
      <para>
-      Returns whether the ScanKey is consistent with the given indexed
-      values for a range.
+      Returns whether all the ScanKey entries are consistent with the given
+      indexed values for a range.
       The attribute number to use is passed as part of the scan key.
+      Multiple scan keys for the same attribute may be passed at once, the
+      number of entries is determined by the <literal>nkeys</literal> parameter.
      </para>
     </listitem>
    </varlistentry>
diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..743f2a925a 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,40 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
+					Oid			collation;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
-
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
-
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					/* skip attributes without any scan keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
+
+					bval = &dtup->bt_columns[attno - 1];
+
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * XXX We simply use the collation from the first key (it
+					 * has to be the same for all keys for the same attribue).
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
+					collation = keys[attno - 1][0]->sk_collation;
+
+					/* Check all keys at once */
+					add = FunctionCall4Coll(&consistentFn[attno - 1],
+											collation,
 											PointerGetDatum(bdesc),
 											PointerGetDatum(bval),
-											PointerGetDatum(key));
+											PointerGetDatum(keys[attno - 1]),
+											Int32GetDatum(nkeys[attno - 1]));
 					addrange = DatumGetBool(add);
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..a260074c91 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -251,6 +253,10 @@ brin_inclusion_add_value(PG_FUNCTION_ARGS)
 /*
  * BRIN inclusion consistent function
  *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
+ *
  * All of the strategies are optional.
  */
 Datum
@@ -258,24 +264,31 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/* Handle IS NULL/IS NOT NULL tests */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -284,7 +297,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -293,7 +311,14 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
@@ -301,10 +326,45 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all regular scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* Skip IS NULL/IS NOT NULL keys (already handled above). */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
+	/* This should be called only for regular keys, not for IS [NOT] NULL. */
+	Assert(!(key->sk_flags & SK_ISNULL));
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +384,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +444,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +464,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +483,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +518,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +528,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..e116084a02 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -140,29 +142,41 @@ brin_minmax_add_value(PG_FUNCTION_ARGS)
  * Given an index tuple corresponding to a certain page range and a scan key,
  * return whether the scan key is consistent with the index tuple's min/max
  * values.  Return true if so, false otherwise.
+ *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
  */
 Datum
 brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
 	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -171,7 +185,12 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -180,13 +199,52 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
+	}
+
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
+
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +287,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..2c4f9a3eff 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											4, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index c7619f8cd3..cd1eda38ab 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8223,7 +8223,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------D524CD37E77B36A2883A7617
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Move-IS-NOT-NULL-handling-from-BRIN-support-20210311.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Move-IS-NOT-NULL-handling-from-BRIN-support-20210311.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 1/6] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow more advanced opclases in the future.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c           | 158 ++++++++++++++++++-----
 src/backend/access/brin/brin_inclusion.c | 140 ++++++++++++++------
 src/backend/access/brin/brin_minmax.c    |  92 ++++++++++---
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 5 files changed, 303 insertions(+), 95 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..963b7079cf 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,78 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of
+					 * multiple scan keys. We can determine that based on the
+					 * number of arguments - functions with extra parameter
+					 * (number of scan keys) do support this, otherwise we
+					 * have to simply pass the scan keys one by one, as
+					 * before.
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same
+						 * for all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet
+						 * the criteria for a single one of them is enough to
+						 * discard the range as a whole, so break out of the
+						 * loop as soon as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+
+							/* mismatching key, no need to look further  */
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..a260074c91 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -251,6 +253,10 @@ brin_inclusion_add_value(PG_FUNCTION_ARGS)
 /*
  * BRIN inclusion consistent function
  *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
+ *
  * All of the strategies are optional.
  */
 Datum
@@ -258,24 +264,31 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/* Handle IS NULL/IS NOT NULL tests */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -284,7 +297,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -293,7 +311,14 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
@@ -301,10 +326,45 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all regular scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* Skip IS NULL/IS NOT NULL keys (already handled above). */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
+	/* This should be called only for regular keys, not for IS [NOT] NULL. */
+	Assert(!(key->sk_flags & SK_ISNULL));
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +384,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +444,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +464,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +483,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +518,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +528,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..e116084a02 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -140,29 +142,41 @@ brin_minmax_add_value(PG_FUNCTION_ARGS)
  * Given an index tuple corresponding to a certain page range and a scan key,
  * return whether the scan key is consistent with the index tuple's min/max
  * values.  Return true if so, false otherwise.
+ *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
  */
 Datum
 brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
 	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -171,7 +185,12 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -180,13 +199,52 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
+	}
+
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
+
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +287,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 1487710d59..33841e14f2 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8191,7 +8191,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8207,7 +8207,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.26.2


--------------6A37408A2C42B5B56C3B3D49
Content-Type: text/x-patch; charset=UTF-8;
 name="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210303.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Move-IS-NOT-NULL-handling-from-BRIN-support-20210303.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2020-09-12 13:07  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2020-09-12 13:07 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

The code continues to support both the original (one scan key at a time)
and new (all scan keys at once) approaches, depending on whether the
consistent function accepts three or four arguments.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 src/backend/access/brin/brin.c          | 158 +++++++++++++++++++-----
 src/backend/access/brin/brin_validate.c |   4 +-
 2 files changed, 126 insertions(+), 36 deletions(-)

diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..963b7079cf 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,66 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We allocate space for all attributes, so
+	 * that we don't have to bother determining which attributes are used.
+	 *
+	 * XXX The widest table can have ~1600 attributes, so this may allocate a
+	 * couple kilobytes of memory). We could invent a more compact approach
+	 * (with just space for used attributes) but that would make the matching
+	 * more complicated, so it may not be a win.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/*
+	 * Preprocess the scan keys - split them into per-attribute arrays.
+	 */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this index attribute, so init as needed. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible. This may waste a bit of memory, but we only
+			 * expect small number of scan keys in general, so this should be
+			 * negligible, and it's cheaper than having to repalloc
+			 * repeatedly.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +534,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,51 +544,78 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
+					/* skip attributes without any san keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
 
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
+					bval = &dtup->bt_columns[attno - 1];
 
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * The opclass may or may not support processing of
+					 * multiple scan keys. We can determine that based on the
+					 * number of arguments - functions with extra parameter
+					 * (number of scan keys) do support this, otherwise we
+					 * have to simply pass the scan keys one by one, as
+					 * before.
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
-											PointerGetDatum(bdesc),
-											PointerGetDatum(bval),
-											PointerGetDatum(key));
-					addrange = DatumGetBool(add);
+					if (consistentFn[attno - 1].fn_nargs >= 4)
+					{
+						Oid			collation;
+
+						/*
+						 * Collation from the first key (has to be the same
+						 * for all keys for the same attribue).
+						 */
+						collation = keys[attno - 1][0]->sk_collation;
+
+						/* Check all keys at once */
+						add = FunctionCall4Coll(&consistentFn[attno - 1],
+												collation,
+												PointerGetDatum(bdesc),
+												PointerGetDatum(bval),
+												PointerGetDatum(keys[attno - 1]),
+												Int32GetDatum(nkeys[attno - 1]));
+						addrange = DatumGetBool(add);
+					}
+					else
+					{
+						/*
+						 * Check keys one by one
+						 *
+						 * When there are multiple scan keys, failure to meet
+						 * the criteria for a single one of them is enough to
+						 * discard the range as a whole, so break out of the
+						 * loop as soon as a false return value is obtained.
+						 */
+						int			keyno;
+
+						for (keyno = 0; keyno < nkeys[attno - 1]; keyno++)
+						{
+							add = FunctionCall3Coll(&consistentFn[attno - 1],
+													keys[attno - 1][keyno]->sk_collation,
+													PointerGetDatum(bdesc),
+													PointerGetDatum(bval),
+													PointerGetDatum(keys[attno - 1][keyno]));
+							addrange = DatumGetBool(add);
+
+							/* mismatching key, no need to look further  */
+							if (!addrange)
+								break;
+						}
+					}
+
 					if (!addrange)
 						break;
 				}
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..11835d85cd 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											3, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-- 
2.26.2


--------------AC3FFB734F56C5F52D422EFC
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Process-all-scan-keys-in-existing-BRIN-opcl-20210305.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Process-all-scan-keys-in-existing-BRIN-opcl-20210305.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2021-03-21 23:24  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2021-03-21 23:24 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow future opclases to benefit from seeing all keys at once.

This does break existing BRIN opclasses, because the signature of the
consistent function changed. We might support both variants (with 3 and
4 parameters), but that seems pointless.  The opclasses have to be
updated because of the changes to NULL handling anyway, and we're not
aware of any out-of-core BRIN opclasses.  There may be some, but it's
not worth the extra complexity.

Bump catversion, because of pg_proc changes.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Reviewed-by: John Naylor <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 doc/src/sgml/brin.sgml                   |   8 +-
 src/backend/access/brin/brin.c           | 116 +++++++++++++------
 src/backend/access/brin/brin_inclusion.c | 140 ++++++++++++++++-------
 src/backend/access/brin/brin_minmax.c    |  92 ++++++++++++---
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/catversion.h         |   2 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 7 files changed, 268 insertions(+), 98 deletions(-)

diff --git a/doc/src/sgml/brin.sgml b/doc/src/sgml/brin.sgml
index 06880c0f7b..078f51bb55 100644
--- a/doc/src/sgml/brin.sgml
+++ b/doc/src/sgml/brin.sgml
@@ -464,12 +464,14 @@ typedef struct BrinOpcInfo
 
    <varlistentry>
     <term><function>bool consistent(BrinDesc *bdesc, BrinValues *column,
-       ScanKey key)</function></term>
+       ScanKey *keys, int nkeys)</function></term>
     <listitem>
      <para>
-      Returns whether the ScanKey is consistent with the given indexed
-      values for a range.
+      Returns whether all the ScanKey entries are consistent with the given
+      indexed values for a range.
       The attribute number to use is passed as part of the scan key.
+      Multiple scan keys for the same attribute may be passed at once, the
+      number of entries is determined by the <literal>nkeys</literal> parameter.
      </para>
     </listitem>
    </varlistentry>
diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..33f4e2c15c 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,65 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We don't know which attributes have scan
+	 * keys, so we allocate space for all attributes. That may use more memory
+	 * but it's probably cheaper than determining which attributes are used.
+	 *
+	 * XXX The widest index can have 32 attributes, so the amount of wasted
+	 * memory is negligible. We could invent a more compact approach (with
+	 * just space for used attributes) but that would make the matching more
+	 * complex so it's not a good trade-off.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/* Preprocess the scan keys - split them into per-attribute arrays. */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this attribute, so init the array of keys. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible (as if all keys were for this attribute). This
+			 * may waste a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible, and
+			 * repeated repalloc calls are not free either.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +533,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,50 +543,38 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
+					Oid			collation;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
-
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
-
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					/* skip attributes without any scan keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
+
+					bval = &dtup->bt_columns[attno - 1];
+
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * XXX We simply use the collation from the first key (it
+					 * has to be the same for all keys for the same attribue).
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
+					collation = keys[attno - 1][0]->sk_collation;
+
+					/* Check all keys at once */
+					add = FunctionCall4Coll(&consistentFn[attno - 1],
+											collation,
 											PointerGetDatum(bdesc),
 											PointerGetDatum(bval),
-											PointerGetDatum(key));
+											PointerGetDatum(keys[attno - 1]),
+											Int32GetDatum(nkeys[attno - 1]));
 					addrange = DatumGetBool(add);
 					if (!addrange)
 						break;
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..cf2d029048 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -251,6 +253,10 @@ brin_inclusion_add_value(PG_FUNCTION_ARGS)
 /*
  * BRIN inclusion consistent function
  *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches the IS NULL keys, we check the regular scan keys.
+ *
  * All of the strategies are optional.
  */
 Datum
@@ -258,24 +264,31 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/* Handle IS NULL/IS NOT NULL tests */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -284,7 +297,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -293,7 +311,14 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
@@ -301,10 +326,45 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all regular scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* Skip IS NULL/IS NOT NULL keys (already handled above). */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
+	/* This should be called only for regular keys, not for IS [NOT] NULL. */
+	Assert(!(key->sk_flags & SK_ISNULL));
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +384,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +444,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +464,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +483,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +518,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +528,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..e116084a02 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -140,29 +142,41 @@ brin_minmax_add_value(PG_FUNCTION_ARGS)
  * Given an index tuple corresponding to a certain page range and a scan key,
  * return whether the scan key is consistent with the index tuple's min/max
  * values.  Return true if so, false otherwise.
+ *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
  */
 Datum
 brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
 	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -171,7 +185,12 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -180,13 +199,52 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
+	}
+
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
+
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +287,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..2c4f9a3eff 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											4, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h
index c831b55bf9..5c9ede2578 100644
--- a/src/include/catalog/catversion.h
+++ b/src/include/catalog/catversion.h
@@ -53,6 +53,6 @@
  */
 
 /*							yyyymmddN */
-#define CATALOG_VERSION_NO	202103191
+#define CATALOG_VERSION_NO	202103221
 
 #endif
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index e259531f60..b9f4afba05 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8215,7 +8215,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8231,7 +8231,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.30.2


--------------76348C5C2C314FA585652FE5
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Move-IS-NOT-NULL-handling-from-BRIN-support-20210322.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Move-IS-NOT-NULL-handling-from-BRIN-support-20210322.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* [PATCH 2/8] Pass all scan keys to BRIN consistent function at once
@ 2021-03-21 23:24  Tomas Vondra <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Tomas Vondra @ 2021-03-21 23:24 UTC (permalink / raw)

Passing all scan keys to the BRIN consistent function at once may allow
elimination of additional ranges, which would be impossible when only
passing individual scan keys.

This modifies the existing BRIN opclasses (minmax, inclusion) although
those don't really benefit from this change. The primary purpose of this
is to allow future opclases to benefit from seeing all keys at once.

This does break existing BRIN opclasses, because the signature of the
consistent function changed. We might support both variants (with 3 and
4 parameters), but that seems pointless.  The opclasses have to be
updated because of the changes to NULL handling anyway, and we're not
aware of any out-of-core BRIN opclasses.  There may be some, but it's
not worth the extra complexity.

Bump catversion, because of pg_proc changes.

Author: Tomas Vondra <[email protected]>
Reviewed-by: Alvaro Herrera <[email protected]>
Reviewed-by: Mark Dilger <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Reviewed-by: John Naylor <[email protected]>
Discussion: https://postgr.es/m/[email protected]
---
 doc/src/sgml/brin.sgml                   |   8 +-
 src/backend/access/brin/brin.c           | 116 +++++++++++++------
 src/backend/access/brin/brin_inclusion.c | 140 ++++++++++++++++-------
 src/backend/access/brin/brin_minmax.c    |  92 ++++++++++++---
 src/backend/access/brin/brin_validate.c  |   4 +-
 src/include/catalog/catversion.h         |   2 +-
 src/include/catalog/pg_proc.dat          |   4 +-
 7 files changed, 268 insertions(+), 98 deletions(-)

diff --git a/doc/src/sgml/brin.sgml b/doc/src/sgml/brin.sgml
index 06880c0f7b..078f51bb55 100644
--- a/doc/src/sgml/brin.sgml
+++ b/doc/src/sgml/brin.sgml
@@ -464,12 +464,14 @@ typedef struct BrinOpcInfo
 
    <varlistentry>
     <term><function>bool consistent(BrinDesc *bdesc, BrinValues *column,
-       ScanKey key)</function></term>
+       ScanKey *keys, int nkeys)</function></term>
     <listitem>
      <para>
-      Returns whether the ScanKey is consistent with the given indexed
-      values for a range.
+      Returns whether all the ScanKey entries are consistent with the given
+      indexed values for a range.
       The attribute number to use is passed as part of the scan key.
+      Multiple scan keys for the same attribute may be passed at once, the
+      number of entries is determined by the <literal>nkeys</literal> parameter.
      </para>
     </listitem>
    </varlistentry>
diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 27ba596c6e..33f4e2c15c 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -390,6 +390,9 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	BrinMemTuple *dtup;
 	BrinTuple  *btup = NULL;
 	Size		btupsz = 0;
+	ScanKey   **keys;
+	int		   *nkeys;
+	int			keyno;
 
 	opaque = (BrinOpaque *) scan->opaque;
 	bdesc = opaque->bo_bdesc;
@@ -411,6 +414,65 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 	 */
 	consistentFn = palloc0(sizeof(FmgrInfo) * bdesc->bd_tupdesc->natts);
 
+	/*
+	 * Make room for per-attribute lists of scan keys that we'll pass to the
+	 * consistent support procedure. We don't know which attributes have scan
+	 * keys, so we allocate space for all attributes. That may use more memory
+	 * but it's probably cheaper than determining which attributes are used.
+	 *
+	 * XXX The widest index can have 32 attributes, so the amount of wasted
+	 * memory is negligible. We could invent a more compact approach (with
+	 * just space for used attributes) but that would make the matching more
+	 * complex so it's not a good trade-off.
+	 */
+	keys = palloc0(sizeof(ScanKey *) * bdesc->bd_tupdesc->natts);
+	nkeys = palloc0(sizeof(int) * bdesc->bd_tupdesc->natts);
+
+	/* Preprocess the scan keys - split them into per-attribute arrays. */
+	for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+	{
+		ScanKey		key = &scan->keyData[keyno];
+		AttrNumber	keyattno = key->sk_attno;
+
+		/*
+		 * The collation of the scan key must match the collation used in the
+		 * index column (but only if the search is not IS NULL/ IS NOT NULL).
+		 * Otherwise we shouldn't be using this index ...
+		 */
+		Assert((key->sk_flags & SK_ISNULL) ||
+			   (key->sk_collation ==
+				TupleDescAttr(bdesc->bd_tupdesc,
+							  keyattno - 1)->attcollation));
+
+		/* First time we see this attribute, so init the array of keys. */
+		if (!keys[keyattno - 1])
+		{
+			FmgrInfo   *tmp;
+
+			/*
+			 * This is a bit of an overkill - we don't know how many scan keys
+			 * are there for this attribute, so we simply allocate the largest
+			 * number possible (as if all keys were for this attribute). This
+			 * may waste a bit of memory, but we only expect small number of
+			 * scan keys in general, so this should be negligible, and
+			 * repeated repalloc calls are not free either.
+			 */
+			keys[keyattno - 1] = palloc0(sizeof(ScanKey) * scan->numberOfKeys);
+
+			/* First time this column, so look up consistent function */
+			Assert(consistentFn[keyattno - 1].fn_oid == InvalidOid);
+
+			tmp = index_getprocinfo(idxRel, keyattno,
+									BRIN_PROCNUM_CONSISTENT);
+			fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
+						   CurrentMemoryContext);
+		}
+
+		/* Add key to the per-attribute array. */
+		keys[keyattno - 1][nkeys[keyattno - 1]] = key;
+		nkeys[keyattno - 1]++;
+	}
+
 	/* allocate an initial in-memory tuple, out of the per-range memcxt */
 	dtup = brin_new_memtuple(bdesc);
 
@@ -471,7 +533,7 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 			}
 			else
 			{
-				int			keyno;
+				int			attno;
 
 				/*
 				 * Compare scan keys with summary values stored for the range.
@@ -481,50 +543,38 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 				 * no keys.
 				 */
 				addrange = true;
-				for (keyno = 0; keyno < scan->numberOfKeys; keyno++)
+				for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
 				{
-					ScanKey		key = &scan->keyData[keyno];
-					AttrNumber	keyattno = key->sk_attno;
-					BrinValues *bval = &dtup->bt_columns[keyattno - 1];
+					BrinValues *bval;
 					Datum		add;
+					Oid			collation;
 
-					/*
-					 * The collation of the scan key must match the collation
-					 * used in the index column (but only if the search is not
-					 * IS NULL/ IS NOT NULL).  Otherwise we shouldn't be using
-					 * this index ...
-					 */
-					Assert((key->sk_flags & SK_ISNULL) ||
-						   (key->sk_collation ==
-							TupleDescAttr(bdesc->bd_tupdesc,
-										  keyattno - 1)->attcollation));
-
-					/* First time this column? look up consistent function */
-					if (consistentFn[keyattno - 1].fn_oid == InvalidOid)
-					{
-						FmgrInfo   *tmp;
-
-						tmp = index_getprocinfo(idxRel, keyattno,
-												BRIN_PROCNUM_CONSISTENT);
-						fmgr_info_copy(&consistentFn[keyattno - 1], tmp,
-									   CurrentMemoryContext);
-					}
+					/* skip attributes without any scan keys */
+					if (nkeys[attno - 1] == 0)
+						continue;
+
+					bval = &dtup->bt_columns[attno - 1];
+
+					Assert((nkeys[attno - 1] > 0) &&
+						   (nkeys[attno - 1] <= scan->numberOfKeys));
 
 					/*
 					 * Check whether the scan key is consistent with the page
 					 * range values; if so, have the pages in the range added
 					 * to the output bitmap.
 					 *
-					 * When there are multiple scan keys, failure to meet the
-					 * criteria for a single one of them is enough to discard
-					 * the range as a whole, so break out of the loop as soon
-					 * as a false return value is obtained.
+					 * XXX We simply use the collation from the first key (it
+					 * has to be the same for all keys for the same attribue).
 					 */
-					add = FunctionCall3Coll(&consistentFn[keyattno - 1],
-											key->sk_collation,
+					collation = keys[attno - 1][0]->sk_collation;
+
+					/* Check all keys at once */
+					add = FunctionCall4Coll(&consistentFn[attno - 1],
+											collation,
 											PointerGetDatum(bdesc),
 											PointerGetDatum(bval),
-											PointerGetDatum(key));
+											PointerGetDatum(keys[attno - 1]),
+											Int32GetDatum(nkeys[attno - 1]));
 					addrange = DatumGetBool(add);
 					if (!addrange)
 						break;
diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c
index 12e5bddd1f..cf2d029048 100644
--- a/src/backend/access/brin/brin_inclusion.c
+++ b/src/backend/access/brin/brin_inclusion.c
@@ -85,6 +85,8 @@ static FmgrInfo *inclusion_get_procinfo(BrinDesc *bdesc, uint16 attno,
 										uint16 procnum);
 static FmgrInfo *inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 												 Oid subtype, uint16 strategynum);
+static bool inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column,
+									 ScanKey key, Oid colloid);
 
 
 /*
@@ -251,6 +253,10 @@ brin_inclusion_add_value(PG_FUNCTION_ARGS)
 /*
  * BRIN inclusion consistent function
  *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches the IS NULL keys, we check the regular scan keys.
+ *
  * All of the strategies are optional.
  */
 Datum
@@ -258,24 +264,31 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	Datum		unionval;
-	AttrNumber	attno;
-	Datum		query;
-	FmgrInfo   *finfo;
-	Datum		result;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
-	/* Handle IS NULL/IS NOT NULL tests. */
-	if (key->sk_flags & SK_ISNULL)
+	/* Handle IS NULL/IS NOT NULL tests */
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -284,7 +297,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -293,7 +311,14 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* If it is all nulls, it cannot possibly be consistent. */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
@@ -301,10 +326,45 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 	if (DatumGetBool(column->bv_values[INCLUSION_UNMERGEABLE]))
 		PG_RETURN_BOOL(true);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	query = key->sk_argument;
-	unionval = column->bv_values[INCLUSION_UNION];
+	/* Check that the range is consistent with all regular scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* Skip IS NULL/IS NOT NULL keys (already handled above). */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!inclusion_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_BOOL(false);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+/*
+ * inclusion_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+inclusion_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+						 Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		query = key->sk_argument;
+	Datum		unionval = column->bv_values[INCLUSION_UNION];
+	Datum		result;
+
+	/* This should be called only for regular keys, not for IS [NOT] NULL. */
+	Assert(!(key->sk_flags & SK_ISNULL));
+
 	switch (key->sk_strategy)
 	{
 			/*
@@ -324,49 +384,49 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverLeftStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTRightStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverBelowStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAboveStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTOverAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		case RTAboveStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTOverBelowStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 			/*
 			 * Overlap and contains strategies
@@ -384,7 +444,7 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													key->sk_strategy);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Contained by strategies
@@ -404,9 +464,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 			/*
 			 * Adjacent strategy
@@ -423,12 +483,12 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTOverlapStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTAdjacentStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_DATUM(result);
+			return DatumGetBool(result);
 
 			/*
 			 * Basic comparison strategies
@@ -458,9 +518,9 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTRightStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTSameStrategyNumber:
 		case RTEqualStrategyNumber:
@@ -468,30 +528,30 @@ brin_inclusion_consistent(PG_FUNCTION_ARGS)
 													RTContainsStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterEqualStrategyNumber:
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
 			if (!DatumGetBool(result))
-				PG_RETURN_BOOL(true);
+				return true;
 
-			PG_RETURN_DATUM(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
+			return DatumGetBool(column->bv_values[INCLUSION_CONTAINS_EMPTY]);
 
 		case RTGreaterStrategyNumber:
 			/* no need to check for empty elements */
 			finfo = inclusion_get_strategy_procinfo(bdesc, attno, subtype,
 													RTLeftStrategyNumber);
 			result = FunctionCall2Coll(finfo, colloid, unionval, query);
-			PG_RETURN_BOOL(!DatumGetBool(result));
+			return !DatumGetBool(result);
 
 		default:
 			/* shouldn't happen */
 			elog(ERROR, "invalid strategy number %d", key->sk_strategy);
-			PG_RETURN_BOOL(false);
+			return false;
 	}
 }
 
diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c
index 2ffbd9bf0d..e116084a02 100644
--- a/src/backend/access/brin/brin_minmax.c
+++ b/src/backend/access/brin/brin_minmax.c
@@ -30,6 +30,8 @@ typedef struct MinmaxOpaque
 
 static FmgrInfo *minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno,
 											  Oid subtype, uint16 strategynum);
+static bool minmax_consistent_key(BrinDesc *bdesc, BrinValues *column,
+								  ScanKey key, Oid colloid);
 
 
 Datum
@@ -140,29 +142,41 @@ brin_minmax_add_value(PG_FUNCTION_ARGS)
  * Given an index tuple corresponding to a certain page range and a scan key,
  * return whether the scan key is consistent with the index tuple's min/max
  * values.  Return true if so, false otherwise.
+ *
+ * We inspect the IS NULL scan keys first, which allows us to make a decision
+ * without looking at the contents of the page range. Only when the page range
+ * matches all those keys, we check the regular scan keys.
  */
 Datum
 brin_minmax_consistent(PG_FUNCTION_ARGS)
 {
 	BrinDesc   *bdesc = (BrinDesc *) PG_GETARG_POINTER(0);
 	BrinValues *column = (BrinValues *) PG_GETARG_POINTER(1);
-	ScanKey		key = (ScanKey) PG_GETARG_POINTER(2);
-	Oid			colloid = PG_GET_COLLATION(),
-				subtype;
-	AttrNumber	attno;
-	Datum		value;
-	Datum		matches;
-	FmgrInfo   *finfo;
-
-	Assert(key->sk_attno == column->bv_attno);
+	ScanKey    *keys = (ScanKey *) PG_GETARG_POINTER(2);
+	int			nkeys = PG_GETARG_INT32(3);
+	Oid			colloid = PG_GET_COLLATION();
+	int			keyno;
+	bool		has_regular_keys = false;
 
 	/* handle IS NULL/IS NOT NULL tests */
-	if (key->sk_flags & SK_ISNULL)
+	for (keyno = 0; keyno < nkeys; keyno++)
 	{
+		ScanKey		key = keys[keyno];
+
+		Assert(key->sk_attno == column->bv_attno);
+
+		/* Skip regular scan keys (and remember that we have some). */
+		if ((!key->sk_flags & SK_ISNULL))
+		{
+			has_regular_keys = true;
+			continue;
+		}
+
 		if (key->sk_flags & SK_SEARCHNULL)
 		{
 			if (column->bv_allnulls || column->bv_hasnulls)
-				PG_RETURN_BOOL(true);
+				continue;		/* this key is fine, continue */
+
 			PG_RETURN_BOOL(false);
 		}
 
@@ -171,7 +185,12 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		 * only nulls.
 		 */
 		if (key->sk_flags & SK_SEARCHNOTNULL)
-			PG_RETURN_BOOL(!column->bv_allnulls);
+		{
+			if (column->bv_allnulls)
+				PG_RETURN_BOOL(false);
+
+			continue;
+		}
 
 		/*
 		 * Neither IS NULL nor IS NOT NULL was used; assume all indexable
@@ -180,13 +199,52 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 		PG_RETURN_BOOL(false);
 	}
 
-	/* if the range is all empty, it cannot possibly be consistent */
+	/* If there are no regular keys, the page range is considered consistent. */
+	if (!has_regular_keys)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * If is all nulls, it cannot possibly be consistent (at this point we
+	 * know there are at least some regular scan keys).
+	 */
 	if (column->bv_allnulls)
 		PG_RETURN_BOOL(false);
 
-	attno = key->sk_attno;
-	subtype = key->sk_subtype;
-	value = key->sk_argument;
+	/* Check that the range is consistent with all scan keys. */
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		ScanKey		key = keys[keyno];
+
+		/* ignore IS NULL/IS NOT NULL tests handled above */
+		if (key->sk_flags & SK_ISNULL)
+			continue;
+
+		/*
+		 * When there are multiple scan keys, failure to meet the criteria for
+		 * a single one of them is enough to discard the range as a whole, so
+		 * break out of the loop as soon as a false return value is obtained.
+		 */
+		if (!minmax_consistent_key(bdesc, column, key, colloid))
+			PG_RETURN_DATUM(false);;
+	}
+
+	PG_RETURN_DATUM(true);
+}
+
+/*
+ * minmax_consistent_key
+ *		Determine if the range is consistent with a single scan key.
+ */
+static bool
+minmax_consistent_key(BrinDesc *bdesc, BrinValues *column, ScanKey key,
+					  Oid colloid)
+{
+	FmgrInfo   *finfo;
+	AttrNumber	attno = key->sk_attno;
+	Oid			subtype = key->sk_subtype;
+	Datum		value = key->sk_argument;
+	Datum		matches;
+
 	switch (key->sk_strategy)
 	{
 		case BTLessStrategyNumber:
@@ -229,7 +287,7 @@ brin_minmax_consistent(PG_FUNCTION_ARGS)
 			break;
 	}
 
-	PG_RETURN_DATUM(matches);
+	return DatumGetBool(matches);
 }
 
 /*
diff --git a/src/backend/access/brin/brin_validate.c b/src/backend/access/brin/brin_validate.c
index 6d4253c05e..2c4f9a3eff 100644
--- a/src/backend/access/brin/brin_validate.c
+++ b/src/backend/access/brin/brin_validate.c
@@ -97,8 +97,8 @@ brinvalidate(Oid opclassoid)
 				break;
 			case BRIN_PROCNUM_CONSISTENT:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
-											3, 3, INTERNALOID, INTERNALOID,
-											INTERNALOID);
+											4, 4, INTERNALOID, INTERNALOID,
+											INTERNALOID, INT4OID);
 				break;
 			case BRIN_PROCNUM_UNION:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, true,
diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h
index c831b55bf9..5c9ede2578 100644
--- a/src/include/catalog/catversion.h
+++ b/src/include/catalog/catversion.h
@@ -53,6 +53,6 @@
  */
 
 /*							yyyymmddN */
-#define CATALOG_VERSION_NO	202103191
+#define CATALOG_VERSION_NO	202103221
 
 #endif
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index e259531f60..b9f4afba05 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8215,7 +8215,7 @@
   prosrc => 'brin_minmax_add_value' },
 { oid => '3385', descr => 'BRIN minmax support',
   proname => 'brin_minmax_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_minmax_consistent' },
 { oid => '3386', descr => 'BRIN minmax support',
   proname => 'brin_minmax_union', prorettype => 'bool',
@@ -8231,7 +8231,7 @@
   prosrc => 'brin_inclusion_add_value' },
 { oid => '4107', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_consistent', prorettype => 'bool',
-  proargtypes => 'internal internal internal',
+  proargtypes => 'internal internal internal int4',
   prosrc => 'brin_inclusion_consistent' },
 { oid => '4108', descr => 'BRIN inclusion support',
   proname => 'brin_inclusion_union', prorettype => 'bool',
-- 
2.30.2


--------------76348C5C2C314FA585652FE5
Content-Type: text/x-patch; charset=UTF-8;
 name="0003-Move-IS-NOT-NULL-handling-from-BRIN-support-20210322.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0003-Move-IS-NOT-NULL-handling-from-BRIN-support-20210322.pa";
 filename*1="tch"



^ permalink  raw  reply  [nested|flat] 280+ messages in thread

* Re: lwlocknames.h beautification attempt
@ 2025-03-03 16:40  Robert Haas <[email protected]>
  0 siblings, 0 replies; 280+ messages in thread

From: Robert Haas @ 2025-03-03 16:40 UTC (permalink / raw)
  To: Gurjeet Singh <[email protected]>; +Cc: pgsql-hackers

On Sun, Mar 2, 2025 at 1:10 AM Gurjeet Singh <[email protected]> wrote:
> I propose the following change to the generation script, generate-lwlocknames.pl
>
> -    print $h "#define ${lockname}Lock (&MainLWLockArray[$lockidx].lock)\n";
> +    printf $h "#define %-30s %s\n", "${lockname}Lock", "(&MainLWLockArray[$lockidx].lock)";

-1. That seems worse to me.

-- 
Robert Haas
EDB: http://www.enterprisedb.com






^ permalink  raw  reply  [nested|flat] 280+ messages in thread


end of thread, other threads:[~2025-03-03 16:40 UTC | newest]

Thread overview: 280+ messages (download: mbox mbox.gz follow: Atom feed)
-- links below jump to the message on this page --
2020-09-12 13:07 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/6] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/9] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/6] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/9] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/6] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/6] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/9] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/9] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/9] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/6] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/6] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/6] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/9] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/9] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/6] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/9] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/6] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/6] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/6] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/9] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/9] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/6] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/6] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/9] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/6] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/6] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/9] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/6] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/9] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/6] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/9] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/6] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/9] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/6] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/9] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/6] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/9] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/9] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/6] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/6] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/9] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/9] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/6] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/6] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/6] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/6] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/6] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/6] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/9] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/9] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/6] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/9] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/6] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/6] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/6] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/9] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/9] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/6] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/9] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/6] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/5] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/6] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/9] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/9] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/9] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/9] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/6] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/6] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/9] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/6] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/9] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/9] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/6] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/9] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/9] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/9] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/6] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/9] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/6] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/6] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/9] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/6] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/6] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/6] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/9] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/6] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/6] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/9] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/9] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/6] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/9] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/6] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/6] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/6] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/6] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/6] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/6] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/9] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/9] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/9] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/6] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/9] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/9] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/9] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/6] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/9] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/7] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/9] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/9] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/6] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/9] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/9] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/6] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/9] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/6] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/9] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/6] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/6] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/6] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/9] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/9] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/6] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/9] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/9] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/9] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/9] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/6] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/6] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/9] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/6] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/6] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/9] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/9] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/6] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/9] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 1/9] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2020-09-12 13:07 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2021-03-21 23:24 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2021-03-21 23:24 [PATCH 2/8] Pass all scan keys to BRIN consistent function at once Tomas Vondra <[email protected]>
2025-03-03 16:40 Re: lwlocknames.h beautification attempt Robert Haas <[email protected]>

This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox